@ks89/angular-modal-gallery 11.1.2 → 13.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.
- package/CHANGELOG.md +7 -0
- package/CONTRIBUTING.md +20 -24
- package/LICENSE +1 -1
- package/README.md +11 -6
- package/fesm2022/ks89-angular-modal-gallery.mjs +151 -139
- package/fesm2022/ks89-angular-modal-gallery.mjs.map +1 -1
- package/lib/components/components.d.ts +1 -1
- package/lib/model/action.enum.d.ts +2 -2
- package/package.json +9 -11
- package/public-api.d.ts +23 -18
- package/esm2022/ks89-angular-modal-gallery.mjs +0 -5
- package/esm2022/lib/components/accessibility-default.mjs +0 -41
- package/esm2022/lib/components/accessible.component.mjs +0 -130
- package/esm2022/lib/components/carousel/carousel-previews/carousel-previews.component.mjs +0 -456
- package/esm2022/lib/components/carousel/carousel.component.mjs +0 -738
- package/esm2022/lib/components/components.mjs +0 -50
- package/esm2022/lib/components/current-image/current-image.component.mjs +0 -607
- package/esm2022/lib/components/current-image/loading-spinner/loading-spinner.component.mjs +0 -80
- package/esm2022/lib/components/dots/dots.component.mjs +0 -124
- package/esm2022/lib/components/modal-gallery/attach-to-overlay.service.mjs +0 -42
- package/esm2022/lib/components/modal-gallery/modal-gallery-ref.mjs +0 -103
- package/esm2022/lib/components/modal-gallery/modal-gallery.component.mjs +0 -499
- package/esm2022/lib/components/modal-gallery/modal-gallery.service.mjs +0 -168
- package/esm2022/lib/components/modal-gallery/modal-gallery.tokens.mjs +0 -26
- package/esm2022/lib/components/plain-gallery/plain-gallery.component.mjs +0 -249
- package/esm2022/lib/components/previews/previews.component.mjs +0 -263
- package/esm2022/lib/components/upper-buttons/upper-buttons-default.mjs +0 -76
- package/esm2022/lib/components/upper-buttons/upper-buttons.component.mjs +0 -243
- package/esm2022/lib/directives/a-tag-bg-image.directive.mjs +0 -78
- package/esm2022/lib/directives/click-outside.directive.mjs +0 -91
- package/esm2022/lib/directives/description.directive.mjs +0 -98
- package/esm2022/lib/directives/direction.directive.mjs +0 -73
- package/esm2022/lib/directives/directives.mjs +0 -51
- package/esm2022/lib/directives/fallback-image.directive.mjs +0 -59
- package/esm2022/lib/directives/keyboard-navigation.directive.mjs +0 -64
- package/esm2022/lib/directives/margin.directive.mjs +0 -84
- package/esm2022/lib/directives/max-size.directive.mjs +0 -75
- package/esm2022/lib/directives/size.directive.mjs +0 -76
- package/esm2022/lib/directives/swipe.directive.mjs +0 -116
- package/esm2022/lib/directives/wrap.directive.mjs +0 -74
- package/esm2022/lib/modal-gallery.module.mjs +0 -88
- package/esm2022/lib/model/accessibility.interface.mjs +0 -25
- package/esm2022/lib/model/action.enum.mjs +0 -36
- package/esm2022/lib/model/buttons-config.interface.mjs +0 -62
- package/esm2022/lib/model/carousel-config.interface.mjs +0 -25
- package/esm2022/lib/model/carousel-image-config.interface.mjs +0 -25
- package/esm2022/lib/model/carousel-preview-config.interface.mjs +0 -25
- package/esm2022/lib/model/current-image-config.interface.mjs +0 -25
- package/esm2022/lib/model/description.interface.mjs +0 -33
- package/esm2022/lib/model/dots-config.interface.mjs +0 -25
- package/esm2022/lib/model/image-internal.class.mjs +0 -35
- package/esm2022/lib/model/image.class.mjs +0 -56
- package/esm2022/lib/model/interaction-event.interface.mjs +0 -2
- package/esm2022/lib/model/keyboard-config.interface.mjs +0 -25
- package/esm2022/lib/model/keyboard.enum.mjs +0 -35
- package/esm2022/lib/model/lib-config.interface.mjs +0 -25
- package/esm2022/lib/model/loading-config.interface.mjs +0 -37
- package/esm2022/lib/model/max-size.interface.mjs +0 -25
- package/esm2022/lib/model/modal-gallery-config.interface.mjs +0 -25
- package/esm2022/lib/model/plain-gallery-config.interface.mjs +0 -55
- package/esm2022/lib/model/play-config.interface.mjs +0 -25
- package/esm2022/lib/model/preview-config.interface.mjs +0 -25
- package/esm2022/lib/model/size.interface.mjs +0 -25
- package/esm2022/lib/model/slide-config.interface.mjs +0 -25
- package/esm2022/lib/services/config.service.mjs +0 -388
- package/esm2022/lib/services/id-validator.service.mjs +0 -71
- package/esm2022/lib/utils/image.util.mjs +0 -48
- package/esm2022/lib/utils/user-input.util.mjs +0 -104
- package/esm2022/public-api.mjs +0 -42
|
@@ -1,738 +0,0 @@
|
|
|
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
|
-
// The idea to create a carousel with two Subjects came from ng-bootstrap
|
|
25
|
-
// So a big thank you to the ng-bootstrap team for the interesting implementation that I used here with some customizations.
|
|
26
|
-
import { ChangeDetectionStrategy, Component, EventEmitter, HostBinding, HostListener, Inject, Input, Output, PLATFORM_ID } from '@angular/core';
|
|
27
|
-
import { isPlatformBrowser } from '@angular/common';
|
|
28
|
-
import { Subject, timer } from 'rxjs';
|
|
29
|
-
import { filter, map, switchMap, takeUntil } from 'rxjs/operators';
|
|
30
|
-
import { AccessibleComponent } from '../accessible.component';
|
|
31
|
-
import { ImageEvent } from '../../model/image.class';
|
|
32
|
-
import { Action } from '../../model/action.enum';
|
|
33
|
-
import { getIndex } from '../../utils/image.util';
|
|
34
|
-
import { NEXT, PREV } from '../../utils/user-input.util';
|
|
35
|
-
import { DescriptionStrategy } from '../../model/description.interface';
|
|
36
|
-
import { ConfigService } from '../../services/config.service';
|
|
37
|
-
import * as i0 from "@angular/core";
|
|
38
|
-
import * as i1 from "../modal-gallery/modal-gallery.service";
|
|
39
|
-
import * as i2 from "../../services/config.service";
|
|
40
|
-
import * as i3 from "@angular/common";
|
|
41
|
-
import * as i4 from "./carousel-previews/carousel-previews.component";
|
|
42
|
-
import * as i5 from "../dots/dots.component";
|
|
43
|
-
import * as i6 from "../../directives/size.directive";
|
|
44
|
-
import * as i7 from "../../directives/description.directive";
|
|
45
|
-
import * as i8 from "../../directives/max-size.directive";
|
|
46
|
-
import * as i9 from "../../directives/fallback-image.directive";
|
|
47
|
-
/**
|
|
48
|
-
* Component with configurable inline/plain carousel.
|
|
49
|
-
*/
|
|
50
|
-
export class CarouselComponent extends AccessibleComponent {
|
|
51
|
-
/**
|
|
52
|
-
* Listener to stop the gallery when the mouse pointer is over the current image.
|
|
53
|
-
*/
|
|
54
|
-
onMouseEnter() {
|
|
55
|
-
if (this.id === null || this.id === undefined) {
|
|
56
|
-
throw new Error('Internal library error - id must be defined');
|
|
57
|
-
}
|
|
58
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
59
|
-
if (!libConfig) {
|
|
60
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
61
|
-
}
|
|
62
|
-
if (!libConfig.carouselPlayConfig || !libConfig.carouselPlayConfig.pauseOnHover) {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
this.stopCarousel();
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Listener to play the gallery when the mouse pointer leave the current image.
|
|
69
|
-
*/
|
|
70
|
-
onMouseLeave() {
|
|
71
|
-
if (this.id === null || this.id === undefined) {
|
|
72
|
-
throw new Error('Internal library error - id must be defined');
|
|
73
|
-
}
|
|
74
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
75
|
-
if (!libConfig) {
|
|
76
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
77
|
-
}
|
|
78
|
-
if (!libConfig.carouselPlayConfig || !libConfig.carouselPlayConfig.pauseOnHover || !libConfig.carouselPlayConfig.autoPlay) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
this.playCarousel();
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Listener to navigate carousel images with keyboard (left).
|
|
85
|
-
*/
|
|
86
|
-
onKeyDownLeft() {
|
|
87
|
-
if (this.id === null || this.id === undefined) {
|
|
88
|
-
throw new Error('Internal library error - id must be defined');
|
|
89
|
-
}
|
|
90
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
91
|
-
if (!libConfig) {
|
|
92
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
93
|
-
}
|
|
94
|
-
if (!libConfig.carouselConfig || !libConfig.carouselConfig.keyboardEnable) {
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
this.prevImage();
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Listener to navigate carousel images with keyboard (right).
|
|
101
|
-
*/
|
|
102
|
-
onKeyDownLRight() {
|
|
103
|
-
if (this.id === null || this.id === undefined) {
|
|
104
|
-
throw new Error('Internal library error - id must be defined');
|
|
105
|
-
}
|
|
106
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
107
|
-
if (!libConfig) {
|
|
108
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
109
|
-
}
|
|
110
|
-
if (!libConfig.carouselConfig || !libConfig.carouselConfig.keyboardEnable) {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
this.nextImage();
|
|
114
|
-
}
|
|
115
|
-
constructor(
|
|
116
|
-
// tslint:disable-next-line:no-any
|
|
117
|
-
platformId, ngZone, modalGalleryService, configService, ref) {
|
|
118
|
-
super();
|
|
119
|
-
this.platformId = platformId;
|
|
120
|
-
this.ngZone = ngZone;
|
|
121
|
-
this.modalGalleryService = modalGalleryService;
|
|
122
|
-
this.configService = configService;
|
|
123
|
-
this.ref = ref;
|
|
124
|
-
/**
|
|
125
|
-
* Attribute to set ariaLabel of the host component
|
|
126
|
-
*/
|
|
127
|
-
this.ariaLabel = `Carousel`;
|
|
128
|
-
/**
|
|
129
|
-
* Array of `InternalLibImage` that represent the model of this library with all images,
|
|
130
|
-
* thumbs and so on.
|
|
131
|
-
*/
|
|
132
|
-
this.images = [];
|
|
133
|
-
/**
|
|
134
|
-
* Output to emit an event when an image is clicked.
|
|
135
|
-
*/
|
|
136
|
-
this.clickImage = new EventEmitter();
|
|
137
|
-
/**
|
|
138
|
-
* Output to emit an event when current image is changed.
|
|
139
|
-
*/
|
|
140
|
-
this.changeImage = new EventEmitter();
|
|
141
|
-
/**
|
|
142
|
-
* Output to emit an event when the current image is the first one.
|
|
143
|
-
*/
|
|
144
|
-
this.firstImage = new EventEmitter();
|
|
145
|
-
/**
|
|
146
|
-
* Output to emit an event when the current image is the last one.
|
|
147
|
-
*/
|
|
148
|
-
this.lastImage = new EventEmitter();
|
|
149
|
-
/**
|
|
150
|
-
* Enum of type `Action` that represents a mouse click on a button.
|
|
151
|
-
* Declared here to be used inside the template.
|
|
152
|
-
*/
|
|
153
|
-
this.clickAction = Action.CLICK;
|
|
154
|
-
/**
|
|
155
|
-
* Enum of type `Action` that represents a keyboard action.
|
|
156
|
-
* Declared here to be used inside the template.
|
|
157
|
-
*/
|
|
158
|
-
this.keyboardAction = Action.KEYBOARD;
|
|
159
|
-
/**
|
|
160
|
-
* Boolean that it's true when you are watching the first image (currently visible).
|
|
161
|
-
* False by default
|
|
162
|
-
*/
|
|
163
|
-
this.isFirstImage = false;
|
|
164
|
-
/**
|
|
165
|
-
* Boolean that it's true when you are watching the last image (currently visible).
|
|
166
|
-
* False by default
|
|
167
|
-
*/
|
|
168
|
-
this.isLastImage = false;
|
|
169
|
-
/**
|
|
170
|
-
* Subject to play the carousel.
|
|
171
|
-
*/
|
|
172
|
-
this.start$ = new Subject();
|
|
173
|
-
/**
|
|
174
|
-
* Subject to stop the carousel.
|
|
175
|
-
*/
|
|
176
|
-
this.stop$ = new Subject();
|
|
177
|
-
}
|
|
178
|
-
ngOnInit() {
|
|
179
|
-
if (this.id === null || this.id === undefined) {
|
|
180
|
-
throw new Error('Internal library error - id must be defined');
|
|
181
|
-
}
|
|
182
|
-
if (!this.images || this.images.length === 0) {
|
|
183
|
-
throw new Error('Internal library error - images array must be defined and with at least an element');
|
|
184
|
-
}
|
|
185
|
-
this.configService.setConfig(this.id, this.config);
|
|
186
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
187
|
-
if (!libConfig) {
|
|
188
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
189
|
-
}
|
|
190
|
-
this.currentImage = this.images[0];
|
|
191
|
-
this.carouselDotsConfig = libConfig.carouselDotsConfig;
|
|
192
|
-
this.accessibilityConfig = libConfig.accessibilityConfig;
|
|
193
|
-
this.carouselSlideInfinite = libConfig.carouselSlideInfinite;
|
|
194
|
-
this.carouselConfig = libConfig.carouselConfig;
|
|
195
|
-
this.carouselImageConfig = libConfig.carouselImageConfig;
|
|
196
|
-
this.manageSlideConfig();
|
|
197
|
-
}
|
|
198
|
-
ngOnChanges(changes) {
|
|
199
|
-
if (this.id === null || this.id === undefined) {
|
|
200
|
-
throw new Error('Internal library error - id must be defined');
|
|
201
|
-
}
|
|
202
|
-
// this.configService.setConfig(this.id, this.config);
|
|
203
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
204
|
-
if (!libConfig) {
|
|
205
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
206
|
-
}
|
|
207
|
-
const configChange = changes.config;
|
|
208
|
-
// handle changes of dotsConfig.visible
|
|
209
|
-
if (configChange &&
|
|
210
|
-
!configChange.firstChange &&
|
|
211
|
-
(configChange.previousValue.carouselDotsConfig?.visible !== configChange.currentValue.carouselDotsConfig?.visible || (!configChange.previousValue.carouselDotsConfig && !configChange.currentValue.carouselDotsConfig))) {
|
|
212
|
-
this.configService.setConfig(this.id, {
|
|
213
|
-
carouselDotsConfig: configChange.currentValue?.carouselDotsConfig
|
|
214
|
-
});
|
|
215
|
-
this.carouselDotsConfig = configChange.currentValue?.carouselDotsConfig;
|
|
216
|
-
this.ref.markForCheck();
|
|
217
|
-
}
|
|
218
|
-
// handle changes of carouselConfig.showArrows
|
|
219
|
-
if (configChange &&
|
|
220
|
-
!configChange.firstChange &&
|
|
221
|
-
(configChange.previousValue.carouselConfig?.showArrows !== configChange.currentValue.carouselConfig?.showArrows || (!configChange.previousValue.carouselConfig && !configChange.currentValue.carouselConfig))) {
|
|
222
|
-
this.configService.setConfig(this.id, {
|
|
223
|
-
carouselConfig: configChange.currentValue?.carouselConfig
|
|
224
|
-
});
|
|
225
|
-
this.carouselConfig = configChange.currentValue?.carouselConfig;
|
|
226
|
-
this.ref.markForCheck();
|
|
227
|
-
}
|
|
228
|
-
// handle changes of playConfig starting/stopping the carousel accordingly
|
|
229
|
-
if (configChange &&
|
|
230
|
-
!configChange.firstChange &&
|
|
231
|
-
(configChange.previousValue.carouselPlayConfig?.autoPlay !== configChange.currentValue.carouselPlayConfig?.autoPlay || (!configChange.previousValue.carouselPlayConfig && !configChange.currentValue.carouselPlayConfig))) {
|
|
232
|
-
this.configService.setConfig(this.id, {
|
|
233
|
-
carouselPlayConfig: configChange.currentValue?.carouselPlayConfig
|
|
234
|
-
});
|
|
235
|
-
// this.configPlay = playConfigChange.currentValue;
|
|
236
|
-
// if autoplay is enabled, and this is not the
|
|
237
|
-
// first change (to prevent multiple starts at the beginning)
|
|
238
|
-
if (configChange.currentValue.carouselPlayConfig?.autoPlay && !configChange.firstChange) {
|
|
239
|
-
this.start$.next();
|
|
240
|
-
}
|
|
241
|
-
else {
|
|
242
|
-
this.stopCarousel();
|
|
243
|
-
}
|
|
244
|
-
this.ref.markForCheck();
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
ngAfterContentInit() {
|
|
248
|
-
// interval doesn't play well with SSR and protractor,
|
|
249
|
-
// so we should run it in the browser and outside Angular
|
|
250
|
-
if (isPlatformBrowser(this.platformId)) {
|
|
251
|
-
if (this.id === null || this.id === undefined) {
|
|
252
|
-
throw new Error('Internal library error - id must be defined');
|
|
253
|
-
}
|
|
254
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
255
|
-
if (!libConfig || !libConfig.carouselPlayConfig) {
|
|
256
|
-
throw new Error('Internal library error - libConfig and carouselPlayConfig must be defined');
|
|
257
|
-
}
|
|
258
|
-
this.ngZone.runOutsideAngular(() => {
|
|
259
|
-
this.start$
|
|
260
|
-
.pipe(map(() => libConfig?.carouselPlayConfig?.interval),
|
|
261
|
-
// tslint:disable-next-line:no-any
|
|
262
|
-
filter((interval) => interval > 0), switchMap(interval => timer(interval).pipe(takeUntil(this.stop$))))
|
|
263
|
-
.subscribe(() => this.ngZone.run(() => {
|
|
264
|
-
if (libConfig.carouselPlayConfig?.autoPlay) {
|
|
265
|
-
this.nextImage();
|
|
266
|
-
}
|
|
267
|
-
this.ref.markForCheck();
|
|
268
|
-
}));
|
|
269
|
-
this.start$.next();
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* Method called when a dot is clicked and used to update the current image.
|
|
275
|
-
* @param number index of the clicked dot
|
|
276
|
-
*/
|
|
277
|
-
onClickDot(index) {
|
|
278
|
-
this.changeCurrentImage(this.images[index], Action.NORMAL);
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Method called by events from both keyboard and mouse on a navigation arrow.
|
|
282
|
-
* @param string direction of the navigation that can be either 'next' or 'prev'
|
|
283
|
-
* @param KeyboardEvent | MouseEvent event payload
|
|
284
|
-
* @param Action action that triggered the event or `Action.NORMAL` if not provided
|
|
285
|
-
*/
|
|
286
|
-
onNavigationEvent(direction, event, action = Action.NORMAL) {
|
|
287
|
-
const result = super.handleNavigationEvent(direction, event);
|
|
288
|
-
if (result === NEXT) {
|
|
289
|
-
this.nextImage(action);
|
|
290
|
-
}
|
|
291
|
-
else if (result === PREV) {
|
|
292
|
-
this.prevImage(action);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
/**
|
|
296
|
-
* Method triggered when you click on the current image.
|
|
297
|
-
* Also, if modalGalleryEnable is true, you can open the modal-gallery.
|
|
298
|
-
*/
|
|
299
|
-
onClickCurrentImage() {
|
|
300
|
-
if (this.id === null || this.id === undefined) {
|
|
301
|
-
throw new Error('Internal library error - id must be defined');
|
|
302
|
-
}
|
|
303
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
304
|
-
if (!libConfig || !libConfig.carouselConfig || !this.currentImage) {
|
|
305
|
-
throw new Error('Internal library error - libConfig, carouselConfig and currentImage must be defined');
|
|
306
|
-
}
|
|
307
|
-
if (!libConfig.carouselConfig.modalGalleryEnable) {
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
const index = getIndex(this.currentImage, this.images);
|
|
311
|
-
this.clickImage.emit(index);
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Method to get the image description based on input params.
|
|
315
|
-
* If you provide a full description this will be the visible description, otherwise,
|
|
316
|
-
* it will be built using the `Description` object, concatenating its fields.
|
|
317
|
-
* @param Image image to get its description. If not provided it will be the current image
|
|
318
|
-
* @returns String description of the image (or the current image if not provided)
|
|
319
|
-
* @throws an Error if description isn't available
|
|
320
|
-
*/
|
|
321
|
-
getDescriptionToDisplay(image = this.currentImage) {
|
|
322
|
-
if (this.id === null || this.id === undefined) {
|
|
323
|
-
throw new Error('Internal library error - id must be defined');
|
|
324
|
-
}
|
|
325
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
326
|
-
if (!libConfig) {
|
|
327
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
328
|
-
}
|
|
329
|
-
const configCurrentImageCarousel = libConfig.carouselImageConfig;
|
|
330
|
-
if (!configCurrentImageCarousel || !configCurrentImageCarousel.description) {
|
|
331
|
-
throw new Error('Description input must be a valid object implementing the Description interface');
|
|
332
|
-
}
|
|
333
|
-
if (!image) {
|
|
334
|
-
throw new Error('Internal library error - image must be defined');
|
|
335
|
-
}
|
|
336
|
-
const imageWithoutDescription = !image || !image.modal || !image.modal.description || image.modal.description === '';
|
|
337
|
-
switch (configCurrentImageCarousel.description.strategy) {
|
|
338
|
-
case DescriptionStrategy.HIDE_IF_EMPTY:
|
|
339
|
-
return imageWithoutDescription ? '' : image.modal.description + '';
|
|
340
|
-
case DescriptionStrategy.ALWAYS_HIDDEN:
|
|
341
|
-
return '';
|
|
342
|
-
default:
|
|
343
|
-
// ----------- DescriptionStrategy.ALWAYS_VISIBLE -----------------
|
|
344
|
-
return this.buildTextDescription(image, imageWithoutDescription);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
/**
|
|
348
|
-
* Method used by SwipeDirective to support touch gestures (you can also invert the swipe direction with configCurrentImage.invertSwipe).
|
|
349
|
-
* @param action String that represent the direction of the swipe action. 'swiperight' by default.
|
|
350
|
-
*/
|
|
351
|
-
swipe(action = 'swiperight') {
|
|
352
|
-
if (this.id === null || this.id === undefined) {
|
|
353
|
-
throw new Error('Internal library error - id must be defined');
|
|
354
|
-
}
|
|
355
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
356
|
-
if (!libConfig || !libConfig.carouselImageConfig) {
|
|
357
|
-
throw new Error('Internal library error - libConfig and carouselImageConfig must be defined');
|
|
358
|
-
}
|
|
359
|
-
const configCurrentImageCarousel = libConfig.carouselImageConfig;
|
|
360
|
-
switch (action) {
|
|
361
|
-
case 'swiperight':
|
|
362
|
-
if (configCurrentImageCarousel.invertSwipe) {
|
|
363
|
-
this.prevImage(Action.SWIPE);
|
|
364
|
-
}
|
|
365
|
-
else {
|
|
366
|
-
this.nextImage(Action.SWIPE);
|
|
367
|
-
}
|
|
368
|
-
break;
|
|
369
|
-
case 'swipeleft':
|
|
370
|
-
if (configCurrentImageCarousel.invertSwipe) {
|
|
371
|
-
this.nextImage(Action.SWIPE);
|
|
372
|
-
}
|
|
373
|
-
else {
|
|
374
|
-
this.prevImage(Action.SWIPE);
|
|
375
|
-
}
|
|
376
|
-
break;
|
|
377
|
-
// case this.SWIPE_ACTION.UP:
|
|
378
|
-
// break;
|
|
379
|
-
// case this.SWIPE_ACTION.DOWN:
|
|
380
|
-
// break;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
/**
|
|
384
|
-
* Method to go back to the previous image.
|
|
385
|
-
* @param action Enum of type `Action` that represents the source
|
|
386
|
-
* action that moved back to the previous image. `Action.NORMAL` by default.
|
|
387
|
-
*/
|
|
388
|
-
prevImage(action = Action.NORMAL) {
|
|
389
|
-
// check if prevImage should be blocked
|
|
390
|
-
if (this.isPreventSliding(0)) {
|
|
391
|
-
return;
|
|
392
|
-
}
|
|
393
|
-
this.changeCurrentImage(this.getPrevImage(), action);
|
|
394
|
-
this.manageSlideConfig();
|
|
395
|
-
this.start$.next();
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Method to go back to the previous image.
|
|
399
|
-
* @param action Enum of type `Action` that represents the source
|
|
400
|
-
* action that moved to the next image. `Action.NORMAL` by default.
|
|
401
|
-
*/
|
|
402
|
-
nextImage(action = Action.NORMAL) {
|
|
403
|
-
// check if nextImage should be blocked
|
|
404
|
-
if (this.isPreventSliding(this.images.length - 1)) {
|
|
405
|
-
return;
|
|
406
|
-
}
|
|
407
|
-
this.changeCurrentImage(this.getNextImage(), action);
|
|
408
|
-
this.manageSlideConfig();
|
|
409
|
-
this.start$.next();
|
|
410
|
-
}
|
|
411
|
-
/**
|
|
412
|
-
* Method used in the template to track ids in ngFor.
|
|
413
|
-
* @param number index of the array
|
|
414
|
-
* @param Image item of the array
|
|
415
|
-
* @returns number the id of the item
|
|
416
|
-
*/
|
|
417
|
-
trackById(index, item) {
|
|
418
|
-
return item.id;
|
|
419
|
-
}
|
|
420
|
-
/**
|
|
421
|
-
* Method called when an image preview is clicked and used to update the current image.
|
|
422
|
-
* @param event an ImageEvent object with the relative action and the index of the clicked preview.
|
|
423
|
-
*/
|
|
424
|
-
onClickPreview(event) {
|
|
425
|
-
const imageFound = this.images[event.result];
|
|
426
|
-
if (!!imageFound) {
|
|
427
|
-
this.manageSlideConfig();
|
|
428
|
-
this.changeCurrentImage(imageFound, event.action);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
432
|
-
* Method to play carousel.
|
|
433
|
-
*/
|
|
434
|
-
playCarousel() {
|
|
435
|
-
this.start$.next();
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* Stops the carousel from cycling through items.
|
|
439
|
-
*/
|
|
440
|
-
stopCarousel() {
|
|
441
|
-
this.stop$.next();
|
|
442
|
-
}
|
|
443
|
-
// TODO remove this because duplicated
|
|
444
|
-
/**
|
|
445
|
-
* Method to get `alt attribute`.
|
|
446
|
-
* `alt` specifies an alternate text for an image, if the image cannot be displayed.
|
|
447
|
-
* @param Image image to get its alt description. If not provided it will be the current image
|
|
448
|
-
* @returns String alt description of the image (or the current image if not provided)
|
|
449
|
-
*/
|
|
450
|
-
getAltDescriptionByImage(image = this.currentImage) {
|
|
451
|
-
if (!image) {
|
|
452
|
-
return '';
|
|
453
|
-
}
|
|
454
|
-
return image.modal && image.modal.description ? image.modal.description : `Image ${getIndex(image, this.images) + 1}`;
|
|
455
|
-
}
|
|
456
|
-
// TODO remove this because duplicated
|
|
457
|
-
/**
|
|
458
|
-
* Method to get the title attributes based on descriptions.
|
|
459
|
-
* This is useful to prevent accessibility issues, because if DescriptionStrategy is ALWAYS_HIDDEN,
|
|
460
|
-
* it prevents an empty string as title.
|
|
461
|
-
* @param Image image to get its description. If not provided it will be the current image
|
|
462
|
-
* @returns String title of the image based on descriptions
|
|
463
|
-
* @throws an Error if description isn't available
|
|
464
|
-
*/
|
|
465
|
-
getTitleToDisplay(image = this.currentImage) {
|
|
466
|
-
if (this.id === null || this.id === undefined) {
|
|
467
|
-
throw new Error('Internal library error - id must be defined');
|
|
468
|
-
}
|
|
469
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
470
|
-
if (!libConfig || !libConfig.carouselImageConfig) {
|
|
471
|
-
throw new Error('Internal library error - libConfig and carouselImageConfig must be defined');
|
|
472
|
-
}
|
|
473
|
-
const configCurrentImageCarousel = libConfig.carouselImageConfig;
|
|
474
|
-
if (!configCurrentImageCarousel || !configCurrentImageCarousel.description) {
|
|
475
|
-
throw new Error('Description input must be a valid object implementing the Description interface');
|
|
476
|
-
}
|
|
477
|
-
const imageWithoutDescription = !image || !image.modal || !image.modal.description || image.modal.description === '';
|
|
478
|
-
const description = this.buildTextDescription(image, imageWithoutDescription);
|
|
479
|
-
return description;
|
|
480
|
-
}
|
|
481
|
-
/**
|
|
482
|
-
* Method to reset carousel (force image with index 0 to be the current image and re-init also previews)
|
|
483
|
-
*/
|
|
484
|
-
// temporary removed because never tested
|
|
485
|
-
// reset() {
|
|
486
|
-
// if (this.configPlay && this.configPlay.autoPlay) {
|
|
487
|
-
// this.stopCarousel();
|
|
488
|
-
// }
|
|
489
|
-
// this.currentImage = this.images[0];
|
|
490
|
-
// this.handleBoundaries(0);
|
|
491
|
-
// if (this.configPlay && this.configPlay.autoPlay) {
|
|
492
|
-
// this.playCarousel();
|
|
493
|
-
// }
|
|
494
|
-
// this.ref.markForCheck();
|
|
495
|
-
// }
|
|
496
|
-
/**
|
|
497
|
-
* Method to cleanup resources. In fact, this will stop the carousel.
|
|
498
|
-
* This is an angular lifecycle hook that is called when this component is destroyed.
|
|
499
|
-
*/
|
|
500
|
-
ngOnDestroy() {
|
|
501
|
-
this.stopCarousel();
|
|
502
|
-
}
|
|
503
|
-
/**
|
|
504
|
-
* Method to change the current image, receiving the new image as input the relative action.
|
|
505
|
-
* @param image an Image object that represents the new image to set as current.
|
|
506
|
-
* @param action Enum of type `Action` that represents the source action that triggered the change.
|
|
507
|
-
*/
|
|
508
|
-
changeCurrentImage(image, action) {
|
|
509
|
-
if (this.id === null || this.id === undefined) {
|
|
510
|
-
throw new Error('Internal library error - id must be defined');
|
|
511
|
-
}
|
|
512
|
-
this.currentImage = image;
|
|
513
|
-
const index = getIndex(image, this.images);
|
|
514
|
-
// emit first/last event based on newIndex value
|
|
515
|
-
this.emitBoundaryEvent(action, index);
|
|
516
|
-
// emit current visible image index
|
|
517
|
-
this.changeImage.emit(new ImageEvent(this.id, action, index + 1));
|
|
518
|
-
}
|
|
519
|
-
/**
|
|
520
|
-
* Private method to get the next index.
|
|
521
|
-
* This is necessary because at the end, when you call next again, you'll go to the first image.
|
|
522
|
-
* That happens because all modal images are shown like in a circle.
|
|
523
|
-
*/
|
|
524
|
-
getNextImage() {
|
|
525
|
-
if (!this.currentImage) {
|
|
526
|
-
throw new Error('Internal library error - currentImage must be defined');
|
|
527
|
-
}
|
|
528
|
-
const currentIndex = getIndex(this.currentImage, this.images);
|
|
529
|
-
let newIndex = 0;
|
|
530
|
-
if (currentIndex >= 0 && currentIndex < this.images.length - 1) {
|
|
531
|
-
newIndex = currentIndex + 1;
|
|
532
|
-
}
|
|
533
|
-
else {
|
|
534
|
-
newIndex = 0; // start from the first index
|
|
535
|
-
}
|
|
536
|
-
return this.images[newIndex];
|
|
537
|
-
}
|
|
538
|
-
/**
|
|
539
|
-
* Private method to get the previous index.
|
|
540
|
-
* This is necessary because at index 0, when you call prev again, you'll go to the last image.
|
|
541
|
-
* That happens because all modal images are shown like in a circle.
|
|
542
|
-
*/
|
|
543
|
-
getPrevImage() {
|
|
544
|
-
if (!this.currentImage) {
|
|
545
|
-
throw new Error('Internal library error - currentImage must be defined');
|
|
546
|
-
}
|
|
547
|
-
const currentIndex = getIndex(this.currentImage, this.images);
|
|
548
|
-
let newIndex = 0;
|
|
549
|
-
if (currentIndex > 0 && currentIndex <= this.images.length - 1) {
|
|
550
|
-
newIndex = currentIndex - 1;
|
|
551
|
-
}
|
|
552
|
-
else {
|
|
553
|
-
newIndex = this.images.length - 1; // start from the last index
|
|
554
|
-
}
|
|
555
|
-
return this.images[newIndex];
|
|
556
|
-
}
|
|
557
|
-
/**
|
|
558
|
-
* Private method to build a text description.
|
|
559
|
-
* This is used also to create titles.
|
|
560
|
-
* @param Image image to get its description. If not provided it will be the current image.
|
|
561
|
-
* @param boolean imageWithoutDescription is a boolean that it's true if the image hasn't a 'modal' description.
|
|
562
|
-
* @returns String description built concatenating image fields with a specific logic.
|
|
563
|
-
*/
|
|
564
|
-
buildTextDescription(image, imageWithoutDescription) {
|
|
565
|
-
if (this.id === null || this.id === undefined) {
|
|
566
|
-
throw new Error('Internal library error - id must be defined');
|
|
567
|
-
}
|
|
568
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
569
|
-
if (!libConfig || !libConfig.carouselImageConfig) {
|
|
570
|
-
throw new Error('Internal library error - libConfig and carouselImageConfig must be defined');
|
|
571
|
-
}
|
|
572
|
-
const configCurrentImageCarousel = libConfig.carouselImageConfig;
|
|
573
|
-
if (!configCurrentImageCarousel || !configCurrentImageCarousel.description) {
|
|
574
|
-
throw new Error('Description input must be a valid object implementing the Description interface');
|
|
575
|
-
}
|
|
576
|
-
if (!image) {
|
|
577
|
-
throw new Error('Internal library error - image must be defined');
|
|
578
|
-
}
|
|
579
|
-
// If customFullDescription use it, otherwise proceed to build a description
|
|
580
|
-
if (configCurrentImageCarousel.description.customFullDescription && configCurrentImageCarousel.description.customFullDescription !== '') {
|
|
581
|
-
return configCurrentImageCarousel.description.customFullDescription;
|
|
582
|
-
}
|
|
583
|
-
const currentIndex = getIndex(image, this.images);
|
|
584
|
-
// If the current image hasn't a description,
|
|
585
|
-
// prevent to write the ' - ' (or this.description.beforeTextDescription)
|
|
586
|
-
const prevDescription = configCurrentImageCarousel.description.imageText ? configCurrentImageCarousel.description.imageText : '';
|
|
587
|
-
const midSeparator = configCurrentImageCarousel.description.numberSeparator ? configCurrentImageCarousel.description.numberSeparator : '';
|
|
588
|
-
const middleDescription = currentIndex + 1 + midSeparator + this.images.length;
|
|
589
|
-
if (imageWithoutDescription) {
|
|
590
|
-
return prevDescription + middleDescription;
|
|
591
|
-
}
|
|
592
|
-
const currImgDescription = image.modal && image.modal.description ? image.modal.description : '';
|
|
593
|
-
const endDescription = configCurrentImageCarousel.description.beforeTextDescription + currImgDescription;
|
|
594
|
-
return prevDescription + middleDescription + endDescription;
|
|
595
|
-
}
|
|
596
|
-
/**
|
|
597
|
-
* Private method to update both `isFirstImage` and `isLastImage` based on
|
|
598
|
-
* the index of the current image.
|
|
599
|
-
* @param number currentIndex is the index of the current image
|
|
600
|
-
*/
|
|
601
|
-
handleBoundaries(currentIndex) {
|
|
602
|
-
if (this.images.length === 1) {
|
|
603
|
-
this.isFirstImage = true;
|
|
604
|
-
this.isLastImage = true;
|
|
605
|
-
return;
|
|
606
|
-
}
|
|
607
|
-
switch (currentIndex) {
|
|
608
|
-
case 0:
|
|
609
|
-
// execute this only if infinite sliding is disabled
|
|
610
|
-
this.isFirstImage = true;
|
|
611
|
-
this.isLastImage = false;
|
|
612
|
-
break;
|
|
613
|
-
case this.images.length - 1:
|
|
614
|
-
// execute this only if infinite sliding is disabled
|
|
615
|
-
this.isFirstImage = false;
|
|
616
|
-
this.isLastImage = true;
|
|
617
|
-
break;
|
|
618
|
-
default:
|
|
619
|
-
this.isFirstImage = false;
|
|
620
|
-
this.isLastImage = false;
|
|
621
|
-
break;
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
/**
|
|
625
|
-
* Private method to manage boundary arrows and sliding.
|
|
626
|
-
* This is based on the slideConfig input to enable/disable 'infinite sliding'.
|
|
627
|
-
* @param number index of the visible image
|
|
628
|
-
*/
|
|
629
|
-
manageSlideConfig() {
|
|
630
|
-
if (this.id === null || this.id === undefined) {
|
|
631
|
-
throw new Error('Internal library error - id must be defined');
|
|
632
|
-
}
|
|
633
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
634
|
-
if (!libConfig) {
|
|
635
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
636
|
-
}
|
|
637
|
-
if (!this.currentImage) {
|
|
638
|
-
throw new Error('Internal library error - currentImage must be defined');
|
|
639
|
-
}
|
|
640
|
-
let index;
|
|
641
|
-
try {
|
|
642
|
-
index = getIndex(this.currentImage, this.images);
|
|
643
|
-
}
|
|
644
|
-
catch (err) {
|
|
645
|
-
console.error('Cannot get the current image index in current-image');
|
|
646
|
-
throw err;
|
|
647
|
-
}
|
|
648
|
-
if (libConfig.carouselSlideInfinite === true) {
|
|
649
|
-
// enable infinite sliding
|
|
650
|
-
this.isFirstImage = false;
|
|
651
|
-
this.isLastImage = false;
|
|
652
|
-
}
|
|
653
|
-
else {
|
|
654
|
-
this.handleBoundaries(index);
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
/**
|
|
658
|
-
* Private method to emit events when either the last or the first image are visible.
|
|
659
|
-
* @param action Enum of type Action that represents the source of the event that changed the
|
|
660
|
-
* current image to the first one or the last one.
|
|
661
|
-
* @param indexToCheck is the index number of the image (the first or the last one).
|
|
662
|
-
*/
|
|
663
|
-
emitBoundaryEvent(action, indexToCheck) {
|
|
664
|
-
if (this.id === null || this.id === undefined) {
|
|
665
|
-
return;
|
|
666
|
-
}
|
|
667
|
-
// to emit first/last event
|
|
668
|
-
switch (indexToCheck) {
|
|
669
|
-
case 0:
|
|
670
|
-
this.firstImage.emit(new ImageEvent(this.id, action, true));
|
|
671
|
-
break;
|
|
672
|
-
case this.images.length - 1:
|
|
673
|
-
this.lastImage.emit(new ImageEvent(this.id, action, true));
|
|
674
|
-
break;
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
/**
|
|
678
|
-
* Private method to check if next/prev actions should be blocked.
|
|
679
|
-
* It checks if carouselSlideInfinite === false and if the image index is equals to the input parameter.
|
|
680
|
-
* If yes, it returns true to say that sliding should be blocked, otherwise not.
|
|
681
|
-
* @param number boundaryIndex that could be either the beginning index (0) or the last index
|
|
682
|
-
* of images (this.images.length - 1).
|
|
683
|
-
* @returns boolean true if carouselSlideInfinite === false and the current index is
|
|
684
|
-
* either the first or the last one.
|
|
685
|
-
*/
|
|
686
|
-
isPreventSliding(boundaryIndex) {
|
|
687
|
-
if (this.id === null || this.id === undefined) {
|
|
688
|
-
throw new Error('Internal library error - id must be defined');
|
|
689
|
-
}
|
|
690
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
691
|
-
if (!libConfig) {
|
|
692
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
693
|
-
}
|
|
694
|
-
if (!this.currentImage) {
|
|
695
|
-
throw new Error('Internal library error - currentImage must be defined');
|
|
696
|
-
}
|
|
697
|
-
return !libConfig.carouselSlideInfinite && getIndex(this.currentImage, this.images) === boundaryIndex;
|
|
698
|
-
}
|
|
699
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: CarouselComponent, deps: [{ token: PLATFORM_ID }, { token: i0.NgZone }, { token: i1.ModalGalleryService }, { token: i2.ConfigService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
700
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.5", type: CarouselComponent, selector: "ks-carousel", inputs: { id: "id", images: "images", config: "config" }, outputs: { clickImage: "clickImage", changeImage: "changeImage", firstImage: "firstImage", lastImage: "lastImage" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "keydown.arrowLeft": "onKeyDownLeft()", "keydown.arrowRight": "onKeyDownLRight()" }, properties: { "attr.aria-label": "this.ariaLabel" } }, providers: [ConfigService], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<main id=\"carousel-container\"\n [attr.aria-label]=\"accessibilityConfig?.carouselContainerAriaLabel\"\n [title]=\"accessibilityConfig?.carouselContainerTitle\"\n ksMaxSize [maxSizeConfig]=\"{maxWidth: carouselConfig?.maxWidth,\n maxHeight: ''}\">\n\n\n <!-- Workaround to support 2 ng-content in the same template in 2 ngIf (https://github.com/angular/angular/issues/22972) -->\n <ng-template #content><ng-content></ng-content></ng-template>\n\n <figure class=\"current-figure\" *ngIf=\"currentImage && currentImage.modal\"\n ksSize [sizeConfig]=\"{width: carouselConfig?.maxWidth,\n height: ''}\">\n\n <a class=\"nav-left\" *ngIf=\"carouselConfig?.showArrows\"\n [attr.aria-label]=\"accessibilityConfig?.carouselPrevImageAriaLabel\"\n [tabIndex]=\"isLastImage && !carouselSlideInfinite ? -1 : 0\" role=\"button\"\n (click)=\"onNavigationEvent('left', $event, clickAction)\" (keyup)=\"onNavigationEvent('left', $event, keyboardAction)\">\n <div class=\"inside {{(isFirstImage && !carouselSlideInfinite) || !carouselConfig.showArrows ? 'empty-arrow-image' : 'left-arrow-image'}}\"\n aria-hidden=\"true\"\n [title]=\"accessibilityConfig?.carouselPrevImageTitle\"></div>\n </a>\n\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\n <picture class=\"current-image\" ksMaxSize [maxSizeConfig]=\"{maxWidth: carouselConfig?.maxWidth,\n maxHeight: carouselConfig?.maxHeight}\">\n <ng-container *ngFor=\"let source of currentImage.modal?.sources\">\n <source [media]=\"source.media\" [srcset]=\"source.srcset\">\n </ng-container>\n <img [id]=\"currentImage.id\"\n [loading]=\"currentImage.loading\"\n [attr.fetchpriority]=\"currentImage.fetchpriority\"\n [style.object-fit]=\"carouselConfig?.objectFit\"\n ksMaxSize [maxSizeConfig]=\"{maxWidth: carouselConfig?.maxWidth,\n maxHeight: carouselConfig?.maxHeight}\"\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 (click)=\"onClickCurrentImage()\"\n (swipeleft)=\"swipe($event.type)\"\n (swiperight)=\"swipe($event.type)\"/>\n </picture>\n <figcaption *ngIf=\"getDescriptionToDisplay() !== ''\"\n class=\"description\"\n ksDescription [description]=\"carouselImageConfig?.description\"\n [innerHTML]=\"getDescriptionToDisplay()\"></figcaption>\n\n <a class=\"nav-right\" *ngIf=\"carouselConfig?.showArrows\"\n [attr.aria-label]=\"accessibilityConfig?.carouselNextImageAriaLabel\"\n [tabIndex]=\"isLastImage && !carouselSlideInfinite ? -1 : 0\" role=\"button\"\n (click)=\"onNavigationEvent('right', $event, clickAction)\" (keyup)=\"onNavigationEvent('right', $event, keyboardAction)\">\n <div class=\"inside {{(isLastImage && !carouselSlideInfinite) || !carouselConfig.showArrows ? 'empty-arrow-image' : 'right-arrow-image'}}\"\n aria-hidden=\"true\"\n [title]=\"accessibilityConfig?.carouselNextImageTitle\"></div>\n </a>\n\n <div id=\"dots\">\n <ks-dots [id]=\"id\"\n [currentImage]=\"currentImage\"\n [images]=\"images\"\n [dotsConfig]=\"carouselDotsConfig\"\n (clickDot)=\"onClickDot($event)\"></ks-dots>\n </div>\n\n </figure>\n\n</main>\n\n<ks-carousel-previews [id]=\"id\"\n [images]=\"images\"\n [currentImage]=\"currentImage\"\n (clickPreview)=\"onClickPreview($event)\"></ks-carousel-previews>\n", styles: [":host{display:flex;flex-direction:column;justify-content:flex-start;align-items:center}#carousel-container{display:flex;flex-direction:row;align-items:center;justify-content:space-between;width:100%}#carousel-container>.current-figure{animation:fadein-visible .8s;text-align:center;margin:0;position:relative}#carousel-container>.current-figure .nav,#carousel-container>.current-figure>.nav-right,#carousel-container>.current-figure>.nav-left{animation:animatezoom 1s;cursor:pointer;transition:all .5s;top:50%;position:absolute}#carousel-container>.current-figure .nav:hover,#carousel-container>.current-figure>.nav-right:hover,#carousel-container>.current-figure>.nav-left:hover{transform:scale(1.1)}#carousel-container>.current-figure>.nav-left{left:5px}#carousel-container>.current-figure>.nav-right{right:5px}#carousel-container>.current-figure>.current-image{display:block}#carousel-container>.current-figure>.current-image>img{width:100%;height:auto;display:block}#carousel-container>.current-figure>figcaption{padding:10px;position:absolute;bottom:0;left:0;right:0}#carousel-container>.current-figure>figcaption .description{font-weight:700;text-align:center}#carousel-container>.current-figure>#dots{position:absolute;bottom:20px;width:100%}\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"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4.CarouselPreviewsComponent, selector: "ks-carousel-previews", inputs: ["id", "currentImage", "images"], outputs: ["clickPreview"] }, { kind: "component", type: i5.DotsComponent, selector: "ks-dots", inputs: ["id", "currentImage", "images", "dotsConfig"], outputs: ["clickDot"] }, { kind: "directive", type: i6.SizeDirective, selector: "[ksSize]", inputs: ["sizeConfig"] }, { kind: "directive", type: i7.DescriptionDirective, selector: "[ksDescription]", inputs: ["description"] }, { kind: "directive", type: i8.MaxSizeDirective, selector: "[ksMaxSize]", inputs: ["maxSizeConfig"] }, { kind: "directive", type: i9.FallbackImageDirective, selector: "[ksFallbackImage]", inputs: ["fallbackImg"], outputs: ["fallbackApplied"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
701
|
-
}
|
|
702
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: CarouselComponent, decorators: [{
|
|
703
|
-
type: Component,
|
|
704
|
-
args: [{ selector: 'ks-carousel', changeDetection: ChangeDetectionStrategy.OnPush, providers: [ConfigService], template: "<main id=\"carousel-container\"\n [attr.aria-label]=\"accessibilityConfig?.carouselContainerAriaLabel\"\n [title]=\"accessibilityConfig?.carouselContainerTitle\"\n ksMaxSize [maxSizeConfig]=\"{maxWidth: carouselConfig?.maxWidth,\n maxHeight: ''}\">\n\n\n <!-- Workaround to support 2 ng-content in the same template in 2 ngIf (https://github.com/angular/angular/issues/22972) -->\n <ng-template #content><ng-content></ng-content></ng-template>\n\n <figure class=\"current-figure\" *ngIf=\"currentImage && currentImage.modal\"\n ksSize [sizeConfig]=\"{width: carouselConfig?.maxWidth,\n height: ''}\">\n\n <a class=\"nav-left\" *ngIf=\"carouselConfig?.showArrows\"\n [attr.aria-label]=\"accessibilityConfig?.carouselPrevImageAriaLabel\"\n [tabIndex]=\"isLastImage && !carouselSlideInfinite ? -1 : 0\" role=\"button\"\n (click)=\"onNavigationEvent('left', $event, clickAction)\" (keyup)=\"onNavigationEvent('left', $event, keyboardAction)\">\n <div class=\"inside {{(isFirstImage && !carouselSlideInfinite) || !carouselConfig.showArrows ? 'empty-arrow-image' : 'left-arrow-image'}}\"\n aria-hidden=\"true\"\n [title]=\"accessibilityConfig?.carouselPrevImageTitle\"></div>\n </a>\n\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\n <picture class=\"current-image\" ksMaxSize [maxSizeConfig]=\"{maxWidth: carouselConfig?.maxWidth,\n maxHeight: carouselConfig?.maxHeight}\">\n <ng-container *ngFor=\"let source of currentImage.modal?.sources\">\n <source [media]=\"source.media\" [srcset]=\"source.srcset\">\n </ng-container>\n <img [id]=\"currentImage.id\"\n [loading]=\"currentImage.loading\"\n [attr.fetchpriority]=\"currentImage.fetchpriority\"\n [style.object-fit]=\"carouselConfig?.objectFit\"\n ksMaxSize [maxSizeConfig]=\"{maxWidth: carouselConfig?.maxWidth,\n maxHeight: carouselConfig?.maxHeight}\"\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 (click)=\"onClickCurrentImage()\"\n (swipeleft)=\"swipe($event.type)\"\n (swiperight)=\"swipe($event.type)\"/>\n </picture>\n <figcaption *ngIf=\"getDescriptionToDisplay() !== ''\"\n class=\"description\"\n ksDescription [description]=\"carouselImageConfig?.description\"\n [innerHTML]=\"getDescriptionToDisplay()\"></figcaption>\n\n <a class=\"nav-right\" *ngIf=\"carouselConfig?.showArrows\"\n [attr.aria-label]=\"accessibilityConfig?.carouselNextImageAriaLabel\"\n [tabIndex]=\"isLastImage && !carouselSlideInfinite ? -1 : 0\" role=\"button\"\n (click)=\"onNavigationEvent('right', $event, clickAction)\" (keyup)=\"onNavigationEvent('right', $event, keyboardAction)\">\n <div class=\"inside {{(isLastImage && !carouselSlideInfinite) || !carouselConfig.showArrows ? 'empty-arrow-image' : 'right-arrow-image'}}\"\n aria-hidden=\"true\"\n [title]=\"accessibilityConfig?.carouselNextImageTitle\"></div>\n </a>\n\n <div id=\"dots\">\n <ks-dots [id]=\"id\"\n [currentImage]=\"currentImage\"\n [images]=\"images\"\n [dotsConfig]=\"carouselDotsConfig\"\n (clickDot)=\"onClickDot($event)\"></ks-dots>\n </div>\n\n </figure>\n\n</main>\n\n<ks-carousel-previews [id]=\"id\"\n [images]=\"images\"\n [currentImage]=\"currentImage\"\n (clickPreview)=\"onClickPreview($event)\"></ks-carousel-previews>\n", styles: [":host{display:flex;flex-direction:column;justify-content:flex-start;align-items:center}#carousel-container{display:flex;flex-direction:row;align-items:center;justify-content:space-between;width:100%}#carousel-container>.current-figure{animation:fadein-visible .8s;text-align:center;margin:0;position:relative}#carousel-container>.current-figure .nav,#carousel-container>.current-figure>.nav-right,#carousel-container>.current-figure>.nav-left{animation:animatezoom 1s;cursor:pointer;transition:all .5s;top:50%;position:absolute}#carousel-container>.current-figure .nav:hover,#carousel-container>.current-figure>.nav-right:hover,#carousel-container>.current-figure>.nav-left:hover{transform:scale(1.1)}#carousel-container>.current-figure>.nav-left{left:5px}#carousel-container>.current-figure>.nav-right{right:5px}#carousel-container>.current-figure>.current-image{display:block}#carousel-container>.current-figure>.current-image>img{width:100%;height:auto;display:block}#carousel-container>.current-figure>figcaption{padding:10px;position:absolute;bottom:0;left:0;right:0}#carousel-container>.current-figure>figcaption .description{font-weight:700;text-align:center}#carousel-container>.current-figure>#dots{position:absolute;bottom:20px;width:100%}\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"] }]
|
|
705
|
-
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
706
|
-
type: Inject,
|
|
707
|
-
args: [PLATFORM_ID]
|
|
708
|
-
}] }, { type: i0.NgZone }, { type: i1.ModalGalleryService }, { type: i2.ConfigService }, { type: i0.ChangeDetectorRef }], propDecorators: { ariaLabel: [{
|
|
709
|
-
type: HostBinding,
|
|
710
|
-
args: ['attr.aria-label']
|
|
711
|
-
}], id: [{
|
|
712
|
-
type: Input
|
|
713
|
-
}], images: [{
|
|
714
|
-
type: Input
|
|
715
|
-
}], config: [{
|
|
716
|
-
type: Input
|
|
717
|
-
}], clickImage: [{
|
|
718
|
-
type: Output
|
|
719
|
-
}], changeImage: [{
|
|
720
|
-
type: Output
|
|
721
|
-
}], firstImage: [{
|
|
722
|
-
type: Output
|
|
723
|
-
}], lastImage: [{
|
|
724
|
-
type: Output
|
|
725
|
-
}], onMouseEnter: [{
|
|
726
|
-
type: HostListener,
|
|
727
|
-
args: ['mouseenter']
|
|
728
|
-
}], onMouseLeave: [{
|
|
729
|
-
type: HostListener,
|
|
730
|
-
args: ['mouseleave']
|
|
731
|
-
}], onKeyDownLeft: [{
|
|
732
|
-
type: HostListener,
|
|
733
|
-
args: ['keydown.arrowLeft']
|
|
734
|
-
}], onKeyDownLRight: [{
|
|
735
|
-
type: HostListener,
|
|
736
|
-
args: ['keydown.arrowRight']
|
|
737
|
-
}] } });
|
|
738
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2Fyb3VzZWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMva3M4OS9hbmd1bGFyLW1vZGFsLWdhbGxlcnkvc3JjL2xpYi9jb21wb25lbnRzL2Nhcm91c2VsL2Nhcm91c2VsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2tzODkvYW5ndWxhci1tb2RhbC1nYWxsZXJ5L3NyYy9saWIvY29tcG9uZW50cy9jYXJvdXNlbC9jYXJvdXNlbC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBRUgseUVBQXlFO0FBQ3pFLDRIQUE0SDtBQUU1SCxPQUFPLEVBRUwsdUJBQXVCLEVBRXZCLFNBQVMsRUFDVCxZQUFZLEVBQ1osV0FBVyxFQUNYLFlBQVksRUFDWixNQUFNLEVBQ04sS0FBSyxFQUtMLE1BQU0sRUFDTixXQUFXLEVBR1osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFcEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRW5FLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRzlELE9BQU8sRUFBUyxVQUFVLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDakQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2xELE9BQU8sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDekQsT0FBTyxFQUFFLG1C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QkFBbUI7Z0JBbUJqQyxlQUFlO3NCQURkLFlBQVk7dUJBQUMsb0JBQW9CIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiBUaGUgTUlUIExpY2Vuc2UgKE1JVClcblxuIENvcHlyaWdodCAoQykgMjAxNy0yMDIzIFN0ZWZhbm8gQ2FwcGEgKEtzODkpXG5cbiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcblxuIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG5cbiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTiBJTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFXG4gU09GVFdBUkUuXG4gKi9cblxuLy8gVGhlIGlkZWEgdG8gY3JlYXRlIGEgY2Fyb3VzZWwgd2l0aCB0d28gU3ViamVjdHMgY2FtZSBmcm9tIG5nLWJvb3RzdHJhcFxuLy8gU28gYSBiaWcgdGhhbmsgeW91IHRvIHRoZSBuZy1ib290c3RyYXAgdGVhbSBmb3IgdGhlIGludGVyZXN0aW5nIGltcGxlbWVudGF0aW9uIHRoYXQgSSB1c2VkIGhlcmUgd2l0aCBzb21lIGN1c3RvbWl6YXRpb25zLlxuXG5pbXBvcnQge1xuICBBZnRlckNvbnRlbnRJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0QmluZGluZyxcbiAgSG9zdExpc3RlbmVyLFxuICBJbmplY3QsXG4gIElucHV0LFxuICBOZ1pvbmUsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgUExBVEZPUk1fSUQsXG4gIFNpbXBsZUNoYW5nZSxcbiAgU2ltcGxlQ2hhbmdlc1xufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGlzUGxhdGZvcm1Ccm93c2VyIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcblxuaW1wb3J0IHsgU3ViamVjdCwgdGltZXIgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGZpbHRlciwgbWFwLCBzd2l0Y2hNYXAsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgQWNjZXNzaWJsZUNvbXBvbmVudCB9IGZyb20gJy4uL2FjY2Vzc2libGUuY29tcG9uZW50JztcblxuaW1wb3J0IHsgQWNjZXNzaWJpbGl0eUNvbmZpZyB9IGZyb20gJy4uLy4uL21vZGVsL2FjY2Vzc2liaWxpdHkuaW50ZXJmYWNlJztcbmltcG9ydCB7IEltYWdlLCBJbWFnZUV2ZW50IH0gZnJvbSAnLi4vLi4vbW9kZWwvaW1hZ2UuY2xhc3MnO1xuaW1wb3J0IHsgQWN0aW9uIH0gZnJvbSAnLi4vLi4vbW9kZWwvYWN0aW9uLmVudW0nO1xuaW1wb3J0IHsgZ2V0SW5kZXggfSBmcm9tICcuLi8uLi91dGlscy9pbWFnZS51dGlsJztcbmltcG9ydCB7IE5FWFQsIFBSRVYgfSBmcm9tICcuLi8uLi91dGlscy91c2VyLWlucHV0LnV0aWwnO1xuaW1wb3J0IHsgRGVzY3JpcHRpb25TdHJhdGVneSB9IGZyb20gJy4uLy4uL21vZGVsL2Rlc2NyaXB0aW9uLmludGVyZmFjZSc7XG5pbXBvcnQgeyBEb3RzQ29uZmlnIH0gZnJvbSAnLi4vLi4vbW9kZWwvZG90cy1jb25maWcuaW50ZXJmYWNlJztcbmltcG9ydCB7IENhcm91c2VsQ29uZmlnIH0gZnJvbSAnLi4vLi4vbW9kZWwvY2Fyb3VzZWwtY29uZmlnLmludGVyZmFjZSc7XG5pbXBvcnQgeyBDYXJvdXNlbEltYWdlQ29uZmlnIH0gZnJvbSAnLi4vLi4vbW9kZWwvY2Fyb3VzZWwtaW1hZ2UtY29uZmlnLmludGVyZmFjZSc7XG5pbXBvcnQgeyBDb25maWdTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvY29uZmlnLnNlcnZpY2UnO1xuaW1wb3J0IHsgTW9kYWxHYWxsZXJ5U2VydmljZSB9IGZyb20gJy4uL21vZGFsLWdhbGxlcnkvbW9kYWwtZ2FsbGVyeS5zZXJ2aWNlJztcbmltcG9ydCB7IENhcm91c2VsTGliQ29uZmlnLCBMaWJDb25maWcgfSBmcm9tICcuLi8uLi9tb2RlbC9saWItY29uZmlnLmludGVyZmFjZSc7XG5pbXBvcnQgeyBJbnRlcm5hbExpYkltYWdlIH0gZnJvbSAnLi4vLi4vbW9kZWwvaW1hZ2UtaW50ZXJuYWwuY2xhc3MnO1xuXG4vKipcbiAqIENvbXBvbmVudCB3aXRoIGNvbmZpZ3VyYWJsZSBpbmxpbmUvcGxhaW4gY2Fyb3VzZWwuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2tzLWNhcm91c2VsJyxcbiAgc3R5bGVVcmxzOiBbJ2Nhcm91c2VsLnNjc3MnLCAnLi4vaW1hZ2UtYXJyb3dzLnNjc3MnXSxcbiAgdGVtcGxhdGVVcmw6ICdjYXJvdXNlbC5odG1sJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHByb3ZpZGVyczogW0NvbmZpZ1NlcnZpY2VdXG59KVxuZXhwb3J0IGNsYXNzIENhcm91c2VsQ29tcG9uZW50IGV4dGVuZHMgQWNjZXNzaWJsZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJDb250ZW50SW5pdCwgT25EZXN0cm95LCBPbkNoYW5nZXMge1xuICAvKipcbiAgICogQXR0cmlidXRlIHRvIHNldCBhcmlhTGFiZWwgb2YgdGhlIGhvc3QgY29tcG9uZW50XG4gICAqL1xuICBASG9zdEJpbmRpbmcoJ2F0dHIuYXJpYS1sYWJlbCcpXG4gIGFyaWFMYWJlbCA9IGBDYXJvdXNlbGA7XG4gIC8qKlxuICAgKiBVbmlxdWUgaWQgKD49MCkgb2YgdGhlIGN1cnJlbnQgaW5zdGFuY2Ugb2YgdGhlIGNhcm91c2VsLiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHlvdSBhcmUgdXNpbmdcbiAgICogdGhlIGNhcm91c2VsJ3MgZmVhdHVyZSB0byBvcGVuIG1vZGFsIGdhbGxlcnkuXG4gICAqL1xuICBASW5wdXQoKVxuICBpZDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogQXJyYXkgb2YgYEludGVybmFsTGliSW1hZ2VgIHRoYXQgcmVwcmVzZW50IHRoZSBtb2RlbCBvZiB0aGlzIGxpYnJhcnkgd2l0aCBhbGwgaW1hZ2VzLFxuICAgKiB0aHVtYnMgYW5kIHNvIG9uLlxuICAgKi9cbiAgQElucHV0KClcbiAgaW1hZ2VzOiBJbWFnZVtdID0gW107XG4gIC8qKlxuICAgKiBDYXJvdXNlbExpYkNvbmZpZyBvYmplY3QgdG8gY29uZmlndXJlIGNhcm91c2VsLlxuICAgKi9cbiAgQElucHV0KClcbiAgY29uZmlnOiBDYXJvdXNlbExpYkNvbmZpZyB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogT3V0cHV0IHRvIGVtaXQgYW4gZXZlbnQgd2hlbiBhbiBpbWFnZSBpcyBjbGlja2VkLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIGNsaWNrSW1hZ2U6IEV2ZW50RW1pdHRlcjxudW1iZXI+ID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXI+KCk7XG4gIC8qKlxuICAgKiBPdXRwdXQgdG8gZW1pdCBhbiBldmVudCB3aGVuIGN1cnJlbnQgaW1hZ2UgaXMgY2hhbmdlZC5cbiAgICovXG4gIEBPdXRwdXQoKVxuICBjaGFuZ2VJbWFnZTogRXZlbnRFbWl0dGVyPEltYWdlRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxJbWFnZUV2ZW50PigpO1xuICAvKipcbiAgICogT3V0cHV0IHRvIGVtaXQgYW4gZXZlbnQgd2hlbiB0aGUgY3VycmVudCBpbWFnZSBpcyB0aGUgZmlyc3Qgb25lLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIGZpcnN0SW1hZ2U6IEV2ZW50RW1pdHRlcjxJbWFnZUV2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXI8SW1hZ2VFdmVudD4oKTtcbiAgLyoqXG4gICAqIE91dHB1dCB0byBlbWl0IGFuIGV2ZW50IHdoZW4gdGhlIGN1cnJlbnQgaW1hZ2UgaXMgdGhlIGxhc3Qgb25lLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIGxhc3RJbWFnZTogRXZlbnRFbWl0dGVyPEltYWdlRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxJbWFnZUV2ZW50PigpO1xuXG4gIC8qKlxuICAgKiBPYmplY3Qgb2YgdHlwZSBgQ2Fyb3VzZWxDb25maWdgIHRvIGluaXQgQ2Fyb3VzZWxDb21wb25lbnQncyBmZWF0dXJlcy5cbiAgICogRm9yIGluc3RhbmNlLCBpdCBjb250YWlucyBwYXJhbWV0ZXJzIHRvIGNoYW5nZSB0aGUgc3R5bGUsIGhvdyBpdCBuYXZpZ2F0ZXMgYW5kIHNvIG9uLlxuICAgKi9cbiAgY2Fyb3VzZWxDb25maWc6IENhcm91c2VsQ29uZmlnIHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBPYmplY3Qgb2YgdHlwZSBgRG90c0NvbmZpZ2AgdG8gaW5pdCBEb3RzQ29tcG9uZW50J3MgZmVhdHVyZXMuXG4gICAqIEZvciBpbnN0YW5jZSwgaXQgY29udGFpbnMgYSBwYXJhbSB0byBzaG93L2hpZGUgdGhpcyBjb21wb25lbnQuXG4gICAqL1xuICBjYXJvdXNlbERvdHNDb25maWc6IERvdHNDb25maWcgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBPYmplY3Qgb2YgdHlwZSBgQWNjZXNzaWJpbGl0eUNvbmZpZ2AgdG8gaW5pdCBjdXN0b20gYWNjZXNzaWJpbGl0eSBmZWF0dXJlcy5cbiAgICogRm9yIGluc3RhbmNlLCBpdCBjb250YWlucyB0aXRsZXMsIGFsdCB0ZXh0cywgYXJpYS1sYWJlbHMgYW5kIHNvIG9uLlxuICAgKi9cbiAgYWNjZXNzaWJpbGl0eUNvbmZpZzogQWNjZXNzaWJpbGl0eUNvbmZpZyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIE9iamVjdCBvZiB0eXBlIGBDYXJvdXNlbEltYWdlQ29uZmlnYCB0byBjb25maWd1cmUgdGhlIGN1cnJlbnQgaW1hZ2Ugb2YgdGhlIGNhcm91c2VsLlxuICAgKi9cbiAgY2Fyb3VzZWxJbWFnZUNvbmZpZzogQ2Fyb3VzZWxJbWFnZUNvbmZpZyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIEVuYWJsZS9kaXNhYmxlIGluZmluaXRlIHNsaWRpbmcuXG4gICAqL1xuICBjYXJvdXNlbFNsaWRlSW5maW5pdGU6IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEVudW0gb2YgdHlwZSBgQWN0aW9uYCB0aGF0IHJlcHJlc2VudHMgYSBtb3VzZSBjbGljayBvbiBhIGJ1dHRvbi5cbiAgICogRGVjbGFyZWQgaGVyZSB0byBiZSB1c2VkIGluc2lkZSB0aGUgdGVtcGxhdGUuXG4gICAqL1xuICBjbGlja0FjdGlvbjogQWN0aW9uID0gQWN0aW9uLkNMSUNLO1xuICAvKipcbiAgICogRW51bSBvZiB0eXBlIGBBY3Rpb25gIHRoYXQgcmVwcmVzZW50cyBhIGtleWJvYXJkIGFjdGlvbi5cbiAgICogRGVjbGFyZWQgaGVyZSB0byBiZSB1c2VkIGluc2lkZSB0aGUgdGVtcGxhdGUuXG4gICAqL1xuICBrZXlib2FyZEFjdGlvbjogQWN0aW9uID0gQWN0aW9uLktFWUJPQVJEO1xuICAvKipcbiAgICogYEltYWdlYCB0aGF0IGlzIHZpc2libGUgcmlnaHQgbm93LlxuICAgKi9cbiAgY3VycmVudEltYWdlOiBJbnRlcm5hbExpYkltYWdlIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogQm9vbGVhbiB0aGF0IGl0J3MgdHJ1ZSB3aGVuIHlvdSBhcmUgd2F0Y2hpbmcgdGhlIGZpcnN0IGltYWdlIChjdXJyZW50bHkgdmlzaWJsZSkuXG4gICAqIEZhbHNlIGJ5IGRlZmF1bHRcbiAgICovXG4gIGlzRmlyc3RJbWFnZSA9IGZhbHNlO1xuICAvKipcbiAgICogQm9vbGVhbiB0aGF0IGl0J3MgdHJ1ZSB3aGVuIHlvdSBhcmUgd2F0Y2hpbmcgdGhlIGxhc3QgaW1hZ2UgKGN1cnJlbnRseSB2aXNpYmxlKS5cbiAgICogRmFsc2UgYnkgZGVmYXVsdFxuICAgKi9cbiAgaXNMYXN0SW1hZ2UgPSBmYWxzZTtcblxuICAvKipcbiAgICogU3ViamVjdCB0byBwbGF5IHRoZSBjYXJvdXNlbC5cbiAgICovXG4gIHByaXZhdGUgc3RhcnQkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgLyoqXG4gICAqIFN1YmplY3QgdG8gc3RvcCB0aGUgY2Fyb3VzZWwuXG4gICAqL1xuICBwcml2YXRlIHN0b3AkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAvKipcbiAgICogTGlzdGVuZXIgdG8gc3RvcCB0aGUgZ2FsbGVyeSB3aGVuIHRoZSBtb3VzZSBwb2ludGVyIGlzIG92ZXIgdGhlIGN1cnJlbnQgaW1hZ2UuXG4gICAqL1xuICBASG9zdExpc3RlbmVyKCdtb3VzZWVudGVyJylcbiAgb25Nb3VzZUVudGVyKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmlkID09PSBudWxsIHx8IHRoaXMuaWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gaWQgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IGxpYkNvbmZpZzogTGliQ29uZmlnIHwgdW5kZWZpbmVkID0gdGhpcy5jb25maWdTZXJ2aWNlLmdldENvbmZpZyh0aGlzLmlkKTtcbiAgICBpZiAoIWxpYkNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gbGliQ29uZmlnIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBpZiAoIWxpYkNvbmZpZy5jYXJvdXNlbFBsYXlDb25maWcgfHwgIWxpYkNvbmZpZy5jYXJvdXNlbFBsYXlDb25maWcucGF1c2VPbkhvdmVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc3RvcENhcm91c2VsKCk7XG4gIH1cblxuICAvKipcbiAgICogTGlzdGVuZXIgdG8gcGxheSB0aGUgZ2FsbGVyeSB3aGVuIHRoZSBtb3VzZSBwb2ludGVyIGxlYXZlIHRoZSBjdXJyZW50IGltYWdlLlxuICAgKi9cbiAgQEhvc3RMaXN0ZW5lcignbW91c2VsZWF2ZScpXG4gIG9uTW91c2VMZWF2ZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pZCA9PT0gbnVsbCB8fCB0aGlzLmlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGlkIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBsaWJDb25maWc6IExpYkNvbmZpZyB8IHVuZGVmaW5lZCA9IHRoaXMuY29uZmlnU2VydmljZS5nZXRDb25maWcodGhpcy5pZCk7XG4gICAgaWYgKCFsaWJDb25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGxpYkNvbmZpZyBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgaWYgKCFsaWJDb25maWcuY2Fyb3VzZWxQbGF5Q29uZmlnIHx8ICFsaWJDb25maWcuY2Fyb3VzZWxQbGF5Q29uZmlnLnBhdXNlT25Ib3ZlciB8fCAhbGliQ29uZmlnLmNhcm91c2VsUGxheUNvbmZpZy5hdXRvUGxheSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnBsYXlDYXJvdXNlbCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3RlbmVyIHRvIG5hdmlnYXRlIGNhcm91c2VsIGltYWdlcyB3aXRoIGtleWJvYXJkIChsZWZ0KS5cbiAgICovXG4gIEBIb3N0TGlzdGVuZXIoJ2tleWRvd24uYXJyb3dMZWZ0JylcbiAgb25LZXlEb3duTGVmdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pZCA9PT0gbnVsbCB8fCB0aGlzLmlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGlkIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBsaWJDb25maWc6IExpYkNvbmZpZyB8IHVuZGVmaW5lZCA9IHRoaXMuY29uZmlnU2VydmljZS5nZXRDb25maWcodGhpcy5pZCk7XG4gICAgaWYgKCFsaWJDb25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGxpYkNvbmZpZyBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgaWYgKCFsaWJDb25maWcuY2Fyb3VzZWxDb25maWcgfHwgIWxpYkNvbmZpZy5jYXJvdXNlbENvbmZpZy5rZXlib2FyZEVuYWJsZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnByZXZJbWFnZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3RlbmVyIHRvIG5hdmlnYXRlIGNhcm91c2VsIGltYWdlcyB3aXRoIGtleWJvYXJkIChyaWdodCkuXG4gICAqL1xuICBASG9zdExpc3RlbmVyKCdrZXlkb3duLmFycm93UmlnaHQnKVxuICBvbktleURvd25MUmlnaHQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaWQgPT09IG51bGwgfHwgdGhpcy5pZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBpZCBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgbGliQ29uZmlnOiBMaWJDb25maWcgfCB1bmRlZmluZWQgPSB0aGlzLmNvbmZpZ1NlcnZpY2UuZ2V0Q29uZmlnKHRoaXMuaWQpO1xuICAgIGlmICghbGliQ29uZmlnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBsaWJDb25maWcgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGlmICghbGliQ29uZmlnLmNhcm91c2VsQ29uZmlnIHx8ICFsaWJDb25maWcuY2Fyb3VzZWxDb25maWcua2V5Ym9hcmRFbmFibGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5uZXh0SW1hZ2UoKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1hbnlcbiAgICBASW5qZWN0KFBMQVRGT1JNX0lEKSBwcml2YXRlIHBsYXRmb3JtSWQ6IGFueSxcbiAgICBwcml2YXRlIG5nWm9uZTogTmdab25lLFxuICAgIHByaXZhdGUgbW9kYWxHYWxsZXJ5U2VydmljZTogTW9kYWxHYWxsZXJ5U2VydmljZSxcbiAgICBwcml2YXRlIGNvbmZpZ1NlcnZpY2U6IENvbmZpZ1NlcnZpY2UsXG4gICAgcHJpdmF0ZSByZWY6IENoYW5nZURldGVjdG9yUmVmXG4gICkge1xuICAgIHN1cGVyKCk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pZCA9PT0gbnVsbCB8fCB0aGlzLmlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGlkIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuaW1hZ2VzIHx8IHRoaXMuaW1hZ2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gaW1hZ2VzIGFycmF5IG11c3QgYmUgZGVmaW5lZCBhbmQgd2l0aCBhdCBsZWFzdCBhbiBlbGVtZW50Jyk7XG4gICAgfVxuICAgIHRoaXMuY29uZmlnU2VydmljZS5zZXRDb25maWcodGhpcy5pZCwgdGhpcy5jb25maWcpO1xuXG4gICAgY29uc3QgbGliQ29uZmlnOiBMaWJDb25maWcgfCB1bmRlZmluZWQgPSB0aGlzLmNvbmZpZ1NlcnZpY2UuZ2V0Q29uZmlnKHRoaXMuaWQpO1xuICAgIGlmICghbGliQ29uZmlnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBsaWJDb25maWcgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuXG4gICAgdGhpcy5jdXJyZW50SW1hZ2UgPSB0aGlzLmltYWdlc1swXSBhcyBJbnRlcm5hbExpYkltYWdlO1xuICAgIHRoaXMuY2Fyb3VzZWxEb3RzQ29uZmlnID0gbGliQ29uZmlnLmNhcm91c2VsRG90c0NvbmZpZztcbiAgICB0aGlzLmFjY2Vzc2liaWxpdHlDb25maWcgPSBsaWJDb25maWcuYWNjZXNzaWJpbGl0eUNvbmZpZztcbiAgICB0aGlzLmNhcm91c2VsU2xpZGVJbmZpbml0ZSA9IGxpYkNvbmZpZy5jYXJvdXNlbFNsaWRlSW5maW5pdGU7XG4gICAgdGhpcy5jYXJvdXNlbENvbmZpZyA9IGxpYkNvbmZpZy5jYXJvdXNlbENvbmZpZztcbiAgICB0aGlzLmNhcm91c2VsSW1hZ2VDb25maWcgPSBsaWJDb25maWcuY2Fyb3VzZWxJbWFnZUNvbmZpZztcblxuICAgIHRoaXMubWFuYWdlU2xpZGVDb25maWcoKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pZCA9PT0gbnVsbCB8fCB0aGlzLmlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGlkIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cblxuICAgIC8vIHRoaXMuY29uZmlnU2VydmljZS5zZXRDb25maWcodGhpcy5pZCwgdGhpcy5jb25maWcpO1xuICAgIGNvbnN0IGxpYkNvbmZpZzogTGliQ29uZmlnIHwgdW5kZWZpbmVkID0gdGhpcy5jb25maWdTZXJ2aWNlLmdldENvbmZpZyh0aGlzLmlkKTtcbiAgICBpZiAoIWxpYkNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gbGliQ29uZmlnIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbmZpZ0NoYW5nZTogU2ltcGxlQ2hhbmdlID0gY2hhbmdlcy5jb25maWc7XG5cbiAgICAvLyBoYW5kbGUgY2hhbmdlcyBvZiBkb3RzQ29uZmlnLnZpc2libGVcbiAgICBpZiAoY29uZmlnQ2hhbmdlICYmXG4gICAgICAhY29uZmlnQ2hhbmdlLmZpcnN0Q2hhbmdlICYmXG4gICAgICAoY29uZmlnQ2hhbmdlLnByZXZpb3VzVmFsdWUuY2Fyb3VzZWxEb3RzQ29uZmlnPy52aXNpYmxlICE9PSBjb25maWdDaGFuZ2UuY3VycmVudFZhbHVlLmNhcm91c2VsRG90c0NvbmZpZz8udmlzaWJsZSB8fCAoIWNvbmZpZ0NoYW5nZS5wcmV2aW91c1ZhbHVlLmNhcm91c2VsRG90c0NvbmZpZyAmJiAhY29uZmlnQ2hhbmdlLmN1cnJlbnRWYWx1ZS5jYXJvdXNlbERvdHNDb25maWcpKVxuICAgICkge1xuICAgICAgdGhpcy5jb25maWdTZXJ2aWNlLnNldENvbmZpZyh0aGlzLmlkLCB7XG4gICAgICAgIGNhcm91c2VsRG90c0NvbmZpZzogY29uZmlnQ2hhbmdlLmN1cnJlbnRWYWx1ZT8uY2Fyb3VzZWxEb3RzQ29uZmlnXG4gICAgICB9KTtcbiAgICAgIHRoaXMuY2Fyb3VzZWxEb3RzQ29uZmlnID0gY29uZmlnQ2hhbmdlLmN1cnJlbnRWYWx1ZT8uY2Fyb3VzZWxEb3RzQ29uZmlnO1xuICAgICAgdGhpcy5yZWYubWFya0ZvckNoZWNrKCk7XG4gICAgfVxuICAgIC8vIGhhbmRsZSBjaGFuZ2VzIG9mIGNhcm91c2VsQ29uZmlnLnNob3dBcnJvd3NcbiAgICBpZiAoY29uZmlnQ2hhbmdlICYmXG4gICAgICAhY29uZmlnQ2hhbmdlLmZpcnN0Q2hhbmdlICYmXG4gICAgICAoY29uZmlnQ2hhbmdlLnByZXZpb3VzVmFsdWUuY2Fyb3VzZWxDb25maWc/LnNob3dBcnJvd3MgIT09IGNvbmZpZ0NoYW5nZS5jdXJyZW50VmFsdWUuY2Fyb3VzZWxDb25maWc/LnNob3dBcnJvd3MgfHwgKCFjb25maWdDaGFuZ2UucHJldmlvdXNWYWx1ZS5jYXJvdXNlbENvbmZpZyAmJiAhY29uZmlnQ2hhbmdlLmN1cnJlbnRWYWx1ZS5jYXJvdXNlbENvbmZpZykpXG4gICAgKSB7XG4gICAgICB0aGlzLmNvbmZpZ1NlcnZpY2Uuc2V0Q29uZmlnKHRoaXMuaWQsIHtcbiAgICAgICAgY2Fyb3VzZWxDb25maWc6IGNvbmZpZ0NoYW5nZS5jdXJyZW50VmFsdWU/LmNhcm91c2VsQ29uZmlnXG4gICAgICB9KTtcbiAgICAgIHRoaXMuY2Fyb3VzZWxDb25maWcgPSBjb25maWdDaGFuZ2UuY3VycmVudFZhbHVlPy5jYXJvdXNlbENvbmZpZztcbiAgICAgIHRoaXMucmVmLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cbiAgICAvLyBoYW5kbGUgY2hhbmdlcyBvZiBwbGF5Q29uZmlnIHN0YXJ0aW5nL3N0b3BwaW5nIHRoZSBjYXJvdXNlbCBhY2NvcmRpbmdseVxuICAgIGlmIChjb25maWdDaGFuZ2UgJiZcbiAgICAgICFjb25maWdDaGFuZ2UuZmlyc3RDaGFuZ2UgJiZcbiAgICAgIChjb25maWdDaGFuZ2UucHJldmlvdXNWYWx1ZS5jYXJvdXNlbFBsYXlDb25maWc/LmF1dG9QbGF5ICE9PSBjb25maWdDaGFuZ2UuY3VycmVudFZhbHVlLmNhcm91c2VsUGxheUNvbmZpZz8uYXV0b1BsYXkgfHwgKCFjb25maWdDaGFuZ2UucHJldmlvdXNWYWx1ZS5jYXJvdXNlbFBsYXlDb25maWcgJiYgIWNvbmZpZ0NoYW5nZS5jdXJyZW50VmFsdWUuY2Fyb3VzZWxQbGF5Q29uZmlnKSlcbiAgICApIHtcbiAgICAgIHRoaXMuY29uZmlnU2VydmljZS5zZXRDb25maWcodGhpcy5pZCwge1xuICAgICAgICBjYXJvdXNlbFBsYXlDb25maWc6IGNvbmZpZ0NoYW5nZS5jdXJyZW50VmFsdWU/LmNhcm91c2VsUGxheUNvbmZpZ1xuICAgICAgfSk7XG4gICAgICAvLyB0aGlzLmNvbmZpZ1BsYXkgPSBwbGF5Q29uZmlnQ2hhbmdlLmN1cnJlbnRWYWx1ZTtcbiAgICAgIC8vIGlmIGF1dG9wbGF5IGlzIGVuYWJsZWQsIGFuZCB0aGlzIGlzIG5vdCB0aGVcbiAgICAgIC8vIGZpcnN0IGNoYW5nZSAodG8gcHJldmVudCBtdWx0aXBsZSBzdGFydHMgYXQgdGhlIGJlZ2lubmluZylcbiAgICAgIGlmIChjb25maWdDaGFuZ2UuY3VycmVudFZhbHVlLmNhcm91c2VsUGxheUNvbmZpZz8uYXV0b1BsYXkgJiYgIWNvbmZpZ0NoYW5nZS5maXJzdENoYW5nZSkge1xuICAgICAgICB0aGlzLnN0YXJ0JC5uZXh0KCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnN0b3BDYXJvdXNlbCgpO1xuICAgICAgfVxuICAgICAgdGhpcy5yZWYubWFya0ZvckNoZWNrKCk7XG4gICAgfVxuICB9XG5cbiAgbmdBZnRlckNvbnRlbnRJbml0KCk6IHZvaWQge1xuICAgIC8vIGludGVydmFsIGRvZXNuJ3QgcGxheSB3ZWxsIHdpdGggU1NSIGFuZCBwcm90cmFjdG9yLFxuICAgIC8vIHNvIHdlIHNob3VsZCBydW4gaXQgaW4gdGhlIGJyb3dzZXIgYW5kIG91dHNpZGUgQW5ndWxhclxuICAgIGlmIChpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICBpZiAodGhpcy5pZCA9PT0gbnVsbCB8fCB0aGlzLmlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gaWQgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBsaWJDb25maWc6IExpYkNvbmZpZyB8IHVuZGVmaW5lZCA9IHRoaXMuY29uZmlnU2VydmljZS5nZXRDb25maWcodGhpcy5pZCk7XG4gICAgICBpZiAoIWxpYkNvbmZpZyB8fCAhbGliQ29uZmlnLmNhcm91c2VsUGxheUNvbmZpZykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBsaWJDb25maWcgYW5kIGNhcm91c2VsUGxheUNvbmZpZyBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICAgIH1cbiAgICAgIHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgICAgdGhpcy5zdGFydCRcbiAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgIG1hcCgoKSA9PiBsaWJDb25maWc/LmNhcm91c2VsUGxheUNvbmZpZz8uaW50ZXJ2YWwpLFxuICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWFueVxuICAgICAgICAgICAgZmlsdGVyKChpbnRlcnZhbDogYW55KSA9PiBpbnRlcnZhbCA+IDApLFxuICAgICAgICAgICAgc3dpdGNoTWFwKGludGVydmFsID0+IHRpbWVyKGludGVydmFsKS5waXBlKHRha2VVbnRpbCh0aGlzLnN0b3AkKSkpXG4gICAgICAgICAgKVxuICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT5cbiAgICAgICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChsaWJDb25maWcuY2Fyb3VzZWxQbGF5Q29uZmlnPy5hdXRvUGxheSkge1xuICAgICAgICAgICAgICAgIHRoaXMubmV4dEltYWdlKCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgdGhpcy5yZWYubWFya0ZvckNoZWNrKCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5zdGFydCQubmV4dCgpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCBjYWxsZWQgd2hlbiBhIGRvdCBpcyBjbGlja2VkIGFuZCB1c2VkIHRvIHVwZGF0ZSB0aGUgY3VycmVudCBpbWFnZS5cbiAgICogQHBhcmFtIG51bWJlciBpbmRleCBvZiB0aGUgY2xpY2tlZCBkb3RcbiAgICovXG4gIG9uQ2xpY2tEb3QoaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuY2hhbmdlQ3VycmVudEltYWdlKHRoaXMuaW1hZ2VzW2luZGV4XSBhcyBJbnRlcm5hbExpYkltYWdlLCBBY3Rpb24uTk9STUFMKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgY2FsbGVkIGJ5IGV2ZW50cyBmcm9tIGJvdGgga2V5Ym9hcmQgYW5kIG1vdXNlIG9uIGEgbmF2aWdhdGlvbiBhcnJvdy5cbiAgICogQHBhcmFtIHN0cmluZyBkaXJlY3Rpb24gb2YgdGhlIG5hdmlnYXRpb24gdGhhdCBjYW4gYmUgZWl0aGVyICduZXh0JyBvciAncHJldidcbiAgICogQHBhcmFtIEtleWJvYXJkRXZlbnQgfCBNb3VzZUV2ZW50IGV2ZW50IHBheWxvYWRcbiAgICogQHBhcmFtIEFjdGlvbiBhY3Rpb24gdGhhdCB0cmlnZ2VyZWQgdGhlIGV2ZW50IG9yIGBBY3Rpb24uTk9STUFMYCBpZiBub3QgcHJvdmlkZWRcbiAgICovXG4gIG9uTmF2aWdhdGlvbkV2ZW50KGRpcmVjdGlvbjogc3RyaW5nLCBldmVudDogS2V5Ym9hcmRFdmVudCB8IE1vdXNlRXZlbnQsIGFjdGlvbjogQWN0aW9uID0gQWN0aW9uLk5PUk1BTCk6IHZvaWQge1xuICAgIGNvbnN0IHJlc3VsdDogbnVtYmVyID0gc3VwZXIuaGFuZGxlTmF2aWdhdGlvbkV2ZW50KGRpcmVjdGlvbiwgZXZlbnQpO1xuICAgIGlmIChyZXN1bHQgPT09IE5FWFQpIHtcbiAgICAgIHRoaXMubmV4dEltYWdlKGFjdGlvbik7XG4gICAgfSBlbHNlIGlmIChyZXN1bHQgPT09IFBSRVYpIHtcbiAgICAgIHRoaXMucHJldkltYWdlKGFjdGlvbik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0cmlnZ2VyZWQgd2hlbiB5b3UgY2xpY2sgb24gdGhlIGN1cnJlbnQgaW1hZ2UuXG4gICAqIEFsc28sIGlmIG1vZGFsR2FsbGVyeUVuYWJsZSBpcyB0cnVlLCB5b3UgY2FuIG9wZW4gdGhlIG1vZGFsLWdhbGxlcnkuXG4gICAqL1xuICBvbkNsaWNrQ3VycmVudEltYWdlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmlkID09PSBudWxsIHx8IHRoaXMuaWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gaWQgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IGxpYkNvbmZpZzogTGliQ29uZmlnIHwgdW5kZWZpbmVkID0gdGhpcy5jb25maWdTZXJ2aWNlLmdldENvbmZpZyh0aGlzLmlkKTtcbiAgICBpZiAoIWxpYkNvbmZpZyB8fCAhbGliQ29uZmlnLmNhcm91c2VsQ29uZmlnIHx8ICF0aGlzLmN1cnJlbnRJbWFnZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gbGliQ29uZmlnLCBjYXJvdXNlbENvbmZpZyBhbmQgY3VycmVudEltYWdlIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBpZiAoIWxpYkNvbmZpZy5jYXJvdXNlbENvbmZpZy5tb2RhbEdhbGxlcnlFbmFibGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgaW5kZXggPSBnZXRJbmRleCh0aGlzLmN1cnJlbnRJbWFnZSwgdGhpcy5pbWFnZXMpO1xuICAgIHRoaXMuY2xpY2tJbWFnZS5lbWl0KGluZGV4KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgdG8gZ2V0IHRoZSBpbWFnZSBkZXNjcmlwdGlvbiBiYXNlZCBvbiBpbnB1dCBwYXJhbXMuXG4gICAqIElmIHlvdSBwcm92aWRlIGEgZnVsbCBkZXNjcmlwdGlvbiB0aGlzIHdpbGwgYmUgdGhlIHZpc2libGUgZGVzY3JpcHRpb24sIG90aGVyd2lzZSxcbiAgICogaXQgd2lsbCBiZSBidWlsdCB1c2luZyB0aGUgYERlc2NyaXB0aW9uYCBvYmplY3QsIGNvbmNhdGVuYXRpbmcgaXRzIGZpZWxkcy5cbiAgICogQHBhcmFtIEltYWdlIGltYWdlIHRvIGdldCBpdHMgZGVzY3JpcHRpb24uIElmIG5vdCBwcm92aWRlZCBpdCB3aWxsIGJlIHRoZSBjdXJyZW50IGltYWdlXG4gICAqIEByZXR1cm5zIFN0cmluZyBkZXNjcmlwdGlvbiBvZiB0aGUgaW1hZ2UgKG9yIHRoZSBjdXJyZW50IGltYWdlIGlmIG5vdCBwcm92aWRlZClcbiAgICogQHRocm93cyBhbiBFcnJvciBpZiBkZXNjcmlwdGlvbiBpc24ndCBhdmFpbGFibGVcbiAgICovXG4gIGdldERlc2NyaXB0aW9uVG9EaXNwbGF5KGltYWdlOiBJbWFnZSB8IHVuZGVmaW5lZCA9IHRoaXMuY3VycmVudEltYWdlKTogc3RyaW5nIHtcbiAgICBpZiAodGhpcy5pZCA9PT0gbnVsbCB8fCB0aGlzLmlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGlkIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBsaWJDb25maWc6IExpYkNvbmZpZyB8IHVuZGVmaW5lZCA9IHRoaXMuY29uZmlnU2VydmljZS5nZXRDb25maWcodGhpcy5pZCk7XG4gICAgaWYgKCFsaWJDb25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGxpYkNvbmZpZyBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWw6IENhcm91c2VsSW1hZ2VDb25maWcgfCB1bmRlZmluZWQgPSBsaWJDb25maWcuY2Fyb3VzZWxJbWFnZUNvbmZpZztcbiAgICBpZiAoIWNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsIHx8ICFjb25maWdDdXJyZW50SW1hZ2VDYXJvdXNlbC5kZXNjcmlwdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdEZXNjcmlwdGlvbiBpbnB1dCBtdXN0IGJlIGEgdmFsaWQgb2JqZWN0IGltcGxlbWVudGluZyB0aGUgRGVzY3JpcHRpb24gaW50ZXJmYWNlJyk7XG4gICAgfVxuICAgIGlmICghaW1hZ2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGltYWdlIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBpbWFnZVdpdGhvdXREZXNjcmlwdGlvbjogYm9vbGVhbiA9ICFpbWFnZSB8fCAhaW1hZ2UubW9kYWwgfHwgIWltYWdlLm1vZGFsLmRlc2NyaXB0aW9uIHx8IGltYWdlLm1vZGFsLmRlc2NyaXB0aW9uID09PSAnJztcblxuICAgIHN3aXRjaCAoY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWwuZGVzY3JpcHRpb24uc3RyYXRlZ3kpIHtcbiAgICAgIGNhc2UgRGVzY3JpcHRpb25TdHJhdGVneS5ISURFX0lGX0VNUFRZOlxuICAgICAgICByZXR1cm4gaW1hZ2VXaXRob3V0RGVzY3JpcHRpb24gPyAnJyA6IGltYWdlLm1vZGFsLmRlc2NyaXB0aW9uICsgJyc7XG4gICAgICBjYXNlIERlc2NyaXB0aW9uU3RyYXRlZ3kuQUxXQVlTX0hJRERFTjpcbiAgICAgICAgcmV0dXJuICcnO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0gRGVzY3JpcHRpb25TdHJhdGVneS5BTFdBWVNfVklTSUJMRSAtLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICByZXR1cm4gdGhpcy5idWlsZFRleHREZXNjcmlwdGlvbihpbWFnZSwgaW1hZ2VXaXRob3V0RGVzY3JpcHRpb24pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgdXNlZCBieSBTd2lwZURpcmVjdGl2ZSB0byBzdXBwb3J0IHRvdWNoIGdlc3R1cmVzICh5b3UgY2FuIGFsc28gaW52ZXJ0IHRoZSBzd2lwZSBkaXJlY3Rpb24gd2l0aCBjb25maWdDdXJyZW50SW1hZ2UuaW52ZXJ0U3dpcGUpLlxuICAgKiBAcGFyYW0gYWN0aW9uIFN0cmluZyB0aGF0IHJlcHJlc2VudCB0aGUgZGlyZWN0aW9uIG9mIHRoZSBzd2lwZSBhY3Rpb24uICdzd2lwZXJpZ2h0JyBieSBkZWZhdWx0LlxuICAgKi9cbiAgc3dpcGUoYWN0aW9uID0gJ3N3aXBlcmlnaHQnKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaWQgPT09IG51bGwgfHwgdGhpcy5pZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBpZCBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgbGliQ29uZmlnOiBMaWJDb25maWcgfCB1bmRlZmluZWQgPSB0aGlzLmNvbmZpZ1NlcnZpY2UuZ2V0Q29uZmlnKHRoaXMuaWQpO1xuICAgIGlmICghbGliQ29uZmlnIHx8ICFsaWJDb25maWcuY2Fyb3VzZWxJbWFnZUNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gbGliQ29uZmlnIGFuZCBjYXJvdXNlbEltYWdlQ29uZmlnIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBjb25maWdDdXJyZW50SW1hZ2VDYXJvdXNlbDogQ2Fyb3VzZWxJbWFnZUNvbmZpZyA9IGxpYkNvbmZpZy5jYXJvdXNlbEltYWdlQ29uZmlnO1xuICAgIHN3aXRjaCAoYWN0aW9uKSB7XG4gICAgICBjYXNlICdzd2lwZXJpZ2h0JzpcbiAgICAgICAgaWYgKGNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsLmludmVydFN3aXBlKSB7XG4gICAgICAgICAgdGhpcy5wcmV2SW1hZ2UoQWN0aW9uLlNXSVBFKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLm5leHRJbWFnZShBY3Rpb24uU1dJUEUpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnc3dpcGVsZWZ0JzpcbiAgICAgICAgaWYgKGNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsLmludmVydFN3aXBlKSB7XG4gICAgICAgICAgdGhpcy5uZXh0SW1hZ2UoQWN0aW9uLlNXSVBFKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnByZXZJbWFnZShBY3Rpb24uU1dJUEUpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgLy8gY2FzZSB0aGlzLlNXSVBFX0FDVElPTi5VUDpcbiAgICAgIC8vICAgYnJlYWs7XG4gICAgICAvLyBjYXNlIHRoaXMuU1dJUEVfQUNUSU9OLkRPV046XG4gICAgICAvLyAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgdG8gZ28gYmFjayB0byB0aGUgcHJldmlvdXMgaW1hZ2UuXG4gICAqIEBwYXJhbSBhY3Rpb24gRW51bSBvZiB0eXBlIGBBY3Rpb25gIHRoYXQgcmVwcmVzZW50cyB0aGUgc291cmNlXG4gICAqICBhY3Rpb24gdGhhdCBtb3ZlZCBiYWNrIHRvIHRoZSBwcmV2aW91cyBpbWFnZS4gYEFjdGlvbi5OT1JNQUxgIGJ5IGRlZmF1bHQuXG4gICAqL1xuICBwcmV2SW1hZ2UoYWN0aW9uOiBBY3Rpb24gPSBBY3Rpb24uTk9STUFMKTogdm9pZCB7XG4gICAgLy8gY2hlY2sgaWYgcHJldkltYWdlIHNob3VsZCBiZSBibG9ja2VkXG4gICAgaWYgKHRoaXMuaXNQcmV2ZW50U2xpZGluZygwKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmNoYW5nZUN1cnJlbnRJbWFnZSh0aGlzLmdldFByZXZJbWFnZSgpLCBhY3Rpb24pO1xuXG4gICAgdGhpcy5tYW5hZ2VTbGlkZUNvbmZpZygpO1xuXG4gICAgdGhpcy5zdGFydCQubmV4dCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0byBnbyBiYWNrIHRvIHRoZSBwcmV2aW91cyBpbWFnZS5cbiAgICogQHBhcmFtIGFjdGlvbiBFbnVtIG9mIHR5cGUgYEFjdGlvbmAgdGhhdCByZXByZXNlbnRzIHRoZSBzb3VyY2VcbiAgICogIGFjdGlvbiB0aGF0IG1vdmVkIHRvIHRoZSBuZXh0IGltYWdlLiBgQWN0aW9uLk5PUk1BTGAgYnkgZGVmYXVsdC5cbiAgICovXG4gIG5leHRJbWFnZShhY3Rpb246IEFjdGlvbiA9IEFjdGlvbi5OT1JNQUwpOiB2b2lkIHtcbiAgICAvLyBjaGVjayBpZiBuZXh0SW1hZ2Ugc2hvdWxkIGJlIGJsb2NrZWRcbiAgICBpZiAodGhpcy5pc1ByZXZlbnRTbGlkaW5nKHRoaXMuaW1hZ2VzLmxlbmd0aCAtIDEpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuY2hhbmdlQ3VycmVudEltYWdlKHRoaXMuZ2V0TmV4dEltYWdlKCksIGFjdGlvbik7XG5cbiAgICB0aGlzLm1hbmFnZVNsaWRlQ29uZmlnKCk7XG5cbiAgICB0aGlzLnN0YXJ0JC5uZXh0KCk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHVzZWQgaW4gdGhlIHRlbXBsYXRlIHRvIHRyYWNrIGlkcyBpbiBuZ0Zvci5cbiAgICogQHBhcmFtIG51bWJlciBpbmRleCBvZiB0aGUgYXJyYXlcbiAgICogQHBhcmFtIEltYWdlIGl0ZW0gb2YgdGhlIGFycmF5XG4gICAqIEByZXR1cm5zIG51bWJlciB0aGUgaWQgb2YgdGhlIGl0ZW1cbiAgICovXG4gIHRyYWNrQnlJZChpbmRleDogbnVtYmVyLCBpdGVtOiBJbWFnZSk6IG51bWJlciB7XG4gICAgcmV0dXJuIGl0ZW0uaWQ7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIGNhbGxlZCB3aGVuIGFuIGltYWdlIHByZXZpZXcgaXMgY2xpY2tlZCBhbmQgdXNlZCB0byB1cGRhdGUgdGhlIGN1cnJlbnQgaW1hZ2UuXG4gICAqIEBwYXJhbSBldmVudCBhbiBJbWFnZUV2ZW50IG9iamVjdCB3aXRoIHRoZSByZWxhdGl2ZSBhY3Rpb24gYW5kIHRoZSBpbmRleCBvZiB0aGUgY2xpY2tlZCBwcmV2aWV3LlxuICAgKi9cbiAgb25DbGlja1ByZXZpZXcoZXZlbnQ6IEltYWdlRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBpbWFnZUZvdW5kOiBJbnRlcm5hbExpYkltYWdlID0gdGhpcy5pbWFnZXNbZXZlbnQucmVzdWx0IGFzIG51bWJlcl0gYXMgSW50ZXJuYWxMaWJJbWFnZTtcbiAgICBpZiAoISFpbWFnZUZvdW5kKSB7XG4gICAgICB0aGlzLm1hbmFnZVNsaWRlQ29uZmlnKCk7XG4gICAgICB0aGlzLmNoYW5nZUN1cnJlbnRJbWFnZShpbWFnZUZvdW5kLCBldmVudC5hY3Rpb24pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgdG8gcGxheSBjYXJvdXNlbC5cbiAgICovXG4gIHBsYXlDYXJvdXNlbCgpOiB2b2lkIHtcbiAgICB0aGlzLnN0YXJ0JC5uZXh0KCk7XG4gIH1cblxuICAvKipcbiAgICogU3RvcHMgdGhlIGNhcm91c2VsIGZyb20gY3ljbGluZyB0aHJvdWdoIGl0ZW1zLlxuICAgKi9cbiAgc3RvcENhcm91c2VsKCk6IHZvaWQge1xuICAgIHRoaXMuc3RvcCQubmV4dCgpO1xuICB9XG5cbiAgLy8gVE9ETyByZW1vdmUgdGhpcyBiZWNhdXNlIGR1cGxpY2F0ZWRcbiAgLyoqXG4gICAqIE1ldGhvZCB0byBnZXQgYGFsdCBhdHRyaWJ1dGVgLlxuICAgKiBgYWx0YCBzcGVjaWZpZXMgYW4gYWx0ZXJuYXRlIHRleHQgZm9yIGFuIGltYWdlLCBpZiB0aGUgaW1hZ2UgY2Fubm90IGJlIGRpc3BsYXllZC5cbiAgICogQHBhcmFtIEltYWdlIGltYWdlIHRvIGdldCBpdHMgYWx0IGRlc2NyaXB0aW9uLiBJZiBub3QgcHJvdmlkZWQgaXQgd2lsbCBiZSB0aGUgY3VycmVudCBpbWFnZVxuICAgKiBAcmV0dXJucyBTdHJpbmcgYWx0IGRlc2NyaXB0aW9uIG9mIHRoZSBpbWFnZSAob3IgdGhlIGN1cnJlbnQgaW1hZ2UgaWYgbm90IHByb3ZpZGVkKVxuICAgKi9cbiAgZ2V0QWx0RGVzY3JpcHRpb25CeUltYWdlKGltYWdlOiBJbWFnZSB8IHVuZGVmaW5lZCA9IHRoaXMuY3VycmVudEltYWdlKTogc3RyaW5nIHtcbiAgICBpZiAoIWltYWdlKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuICAgIHJldHVybiBpbWFnZS5tb2RhbCAmJiBpbWFnZS5tb2RhbC5kZXNjcmlwdGlvbiA/IGltYWdlLm1vZGFsLmRlc2NyaXB0aW9uIDogYEltYWdlICR7Z2V0SW5kZXgoaW1hZ2UsIHRoaXMuaW1hZ2VzKSArIDF9YDtcbiAgfVxuXG4gIC8vIFRPRE8gcmVtb3ZlIHRoaXMgYmVjYXVzZSBkdXBsaWNhdGVkXG4gIC8qKlxuICAgKiBNZXRob2QgdG8gZ2V0IHRoZSB0aXRsZSBhdHRyaWJ1dGVzIGJhc2VkIG9uIGRlc2NyaXB0aW9ucy5cbiAgICogVGhpcyBpcyB1c2VmdWwgdG8gcHJldmVudCBhY2Nlc3NpYmlsaXR5IGlzc3VlcywgYmVjYXVzZSBpZiBEZXNjcmlwdGlvblN0cmF0ZWd5IGlzIEFMV0FZU19ISURERU4sXG4gICAqIGl0IHByZXZlbnRzIGFuIGVtcHR5IHN0cmluZyBhcyB0aXRsZS5cbiAgICogQHBhcmFtIEltYWdlIGltYWdlIHRvIGdldCBpdHMgZGVzY3JpcHRpb24uIElmIG5vdCBwcm92aWRlZCBpdCB3aWxsIGJlIHRoZSBjdXJyZW50IGltYWdlXG4gICAqIEByZXR1cm5zIFN0cmluZyB0aXRsZSBvZiB0aGUgaW1hZ2UgYmFzZWQgb24gZGVzY3JpcHRpb25zXG4gICAqIEB0aHJvd3MgYW4gRXJyb3IgaWYgZGVzY3JpcHRpb24gaXNuJ3QgYXZhaWxhYmxlXG4gICAqL1xuICBnZXRUaXRsZVRvRGlzcGxheShpbWFnZTogSW1hZ2UgfCB1bmRlZmluZWQgPSB0aGlzLmN1cnJlbnRJbWFnZSk6IHN0cmluZyB7XG4gICAgaWYgKHRoaXMuaWQgPT09IG51bGwgfHwgdGhpcy5pZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBpZCBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgbGliQ29uZmlnOiBMaWJDb25maWcgfCB1bmRlZmluZWQgPSB0aGlzLmNvbmZpZ1NlcnZpY2UuZ2V0Q29uZmlnKHRoaXMuaWQpO1xuICAgIGlmICghbGliQ29uZmlnIHx8ICFsaWJDb25maWcuY2Fyb3VzZWxJbWFnZUNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gbGliQ29uZmlnIGFuZCBjYXJvdXNlbEltYWdlQ29uZmlnIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBjb25maWdDdXJyZW50SW1hZ2VDYXJvdXNlbDogQ2Fyb3VzZWxJbWFnZUNvbmZpZyA9IGxpYkNvbmZpZy5jYXJvdXNlbEltYWdlQ29uZmlnO1xuICAgIGlmICghY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWwgfHwgIWNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsLmRlc2NyaXB0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Rlc2NyaXB0aW9uIGlucHV0IG11c3QgYmUgYSB2YWxpZCBvYmplY3QgaW1wbGVtZW50aW5nIHRoZSBEZXNjcmlwdGlvbiBpbnRlcmZhY2UnKTtcbiAgICB9XG4gICAgY29uc3QgaW1hZ2VXaXRob3V0RGVzY3JpcHRpb246IGJvb2xlYW4gPSAhaW1hZ2UgfHwgIWltYWdlLm1vZGFsIHx8ICFpbWFnZS5tb2RhbC5kZXNjcmlwdGlvbiB8fCBpbWFnZS5tb2RhbC5kZXNjcmlwdGlvbiA9PT0gJyc7XG4gICAgY29uc3QgZGVzY3JpcHRpb246IHN0cmluZyA9IHRoaXMuYnVpbGRUZXh0RGVzY3JpcHRpb24oaW1hZ2UsIGltYWdlV2l0aG91dERlc2NyaXB0aW9uKTtcbiAgICByZXR1cm4gZGVzY3JpcHRpb247XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIHJlc2V0IGNhcm91c2VsIChmb3JjZSBpbWFnZSB3aXRoIGluZGV4IDAgdG8gYmUgdGhlIGN1cnJlbnQgaW1hZ2UgYW5kIHJlLWluaXQgYWxzbyBwcmV2aWV3cylcbiAgICovXG4gIC8vIHRlbXBvcmFyeSByZW1vdmVkIGJlY2F1c2UgbmV2ZXIgdGVzdGVkXG4gIC8vIHJlc2V0KCkge1xuICAvLyAgIGlmICh0aGlzLmNvbmZpZ1BsYXkgJiYgdGhpcy5jb25maWdQbGF5LmF1dG9QbGF5KSB7XG4gIC8vICAgICB0aGlzLnN0b3BDYXJvdXNlbCgpO1xuICAvLyAgIH1cbiAgLy8gICB0aGlzLmN1cnJlbnRJbWFnZSA9IHRoaXMuaW1hZ2VzWzBdO1xuICAvLyAgIHRoaXMuaGFuZGxlQm91bmRhcmllcygwKTtcbiAgLy8gICBpZiAodGhpcy5jb25maWdQbGF5ICYmIHRoaXMuY29uZmlnUGxheS5hdXRvUGxheSkge1xuICAvLyAgICAgdGhpcy5wbGF5Q2Fyb3VzZWwoKTtcbiAgLy8gICB9XG4gIC8vICAgdGhpcy5yZWYubWFya0ZvckNoZWNrKCk7XG4gIC8vIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIGNsZWFudXAgcmVzb3VyY2VzLiBJbiBmYWN0LCB0aGlzIHdpbGwgc3RvcCB0aGUgY2Fyb3VzZWwuXG4gICAqIFRoaXMgaXMgYW4gYW5ndWxhciBsaWZlY3ljbGUgaG9vayB0aGF0IGlzIGNhbGxlZCB3aGVuIHRoaXMgY29tcG9uZW50IGlzIGRlc3Ryb3llZC5cbiAgICovXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuc3RvcENhcm91c2VsKCk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIGNoYW5nZSB0aGUgY3VycmVudCBpbWFnZSwgcmVjZWl2aW5nIHRoZSBuZXcgaW1hZ2UgYXMgaW5wdXQgdGhlIHJlbGF0aXZlIGFjdGlvbi5cbiAgICogQHBhcmFtIGltYWdlIGFuIEltYWdlIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgdGhlIG5ldyBpbWFnZSB0byBzZXQgYXMgY3VycmVudC5cbiAgICogQHBhcmFtIGFjdGlvbiBFbnVtIG9mIHR5cGUgYEFjdGlvbmAgdGhhdCByZXByZXNlbnRzIHRoZSBzb3VyY2UgYWN0aW9uIHRoYXQgdHJpZ2dlcmVkIHRoZSBjaGFuZ2UuXG4gICAqL1xuICBwcml2YXRlIGNoYW5nZUN1cnJlbnRJbWFnZShpbWFnZTogSW50ZXJuYWxMaWJJbWFnZSwgYWN0aW9uOiBBY3Rpb24pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pZCA9PT0gbnVsbCB8fCB0aGlzLmlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGlkIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICB0aGlzLmN1cnJlbnRJbWFnZSA9IGltYWdlO1xuICAgIGNvbnN0IGluZGV4OiBudW1iZXIgPSBnZXRJbmRleChpbWFnZSwgdGhpcy5pbWFnZXMpO1xuXG4gICAgLy8gZW1pdCBmaXJzdC9sYXN0IGV2ZW50IGJhc2VkIG9uIG5ld0luZGV4IHZhbHVlXG4gICAgdGhpcy5lbWl0Qm91bmRhcnlFdmVudChhY3Rpb24sIGluZGV4KTtcblxuICAgIC8vIGVtaXQgY3VycmVudCB2aXNpYmxlIGltYWdlIGluZGV4XG4gICAgdGhpcy5jaGFuZ2VJbWFnZS5lbWl0KG5ldyBJbWFnZUV2ZW50KHRoaXMuaWQsIGFjdGlvbiwgaW5kZXggKyAxKSk7XG4gIH1cblxuICAvKipcbiAgICogUHJpdmF0ZSBtZXRob2QgdG8gZ2V0IHRoZSBuZXh0IGluZGV4LlxuICAgKiBUaGlzIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIGF0IHRoZSBlbmQsIHdoZW4geW91IGNhbGwgbmV4dCBhZ2FpbiwgeW91J2xsIGdvIHRvIHRoZSBmaXJzdCBpbWFnZS5cbiAgICogVGhhdCBoYXBwZW5zIGJlY2F1c2UgYWxsIG1vZGFsIGltYWdlcyBhcmUgc2hvd24gbGlrZSBpbiBhIGNpcmNsZS5cbiAgICovXG4gIHByaXZhdGUgZ2V0TmV4dEltYWdlKCk6IEludGVybmFsTGliSW1hZ2Uge1xuICAgIGlmICghdGhpcy5jdXJyZW50SW1hZ2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGN1cnJlbnRJbWFnZSBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgY3VycmVudEluZGV4OiBudW1iZXIgPSBnZXRJbmRleCh0aGlzLmN1cnJlbnRJbWFnZSwgdGhpcy5pbWFnZXMpO1xuICAgIGxldCBuZXdJbmRleCA9IDA7XG4gICAgaWYgKGN1cnJlbnRJbmRleCA+PSAwICYmIGN1cnJlbnRJbmRleCA8IHRoaXMuaW1hZ2VzLmxlbmd0aCAtIDEpIHtcbiAgICAgIG5ld0luZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3SW5kZXggPSAwOyAvLyBzdGFydCBmcm9tIHRoZSBmaXJzdCBpbmRleFxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5pbWFnZXNbbmV3SW5kZXhdIGFzIEludGVybmFsTGliSW1hZ2U7XG4gIH1cblxuICAvKipcbiAgICogUHJpdmF0ZSBtZXRob2QgdG8gZ2V0IHRoZSBwcmV2aW91cyBpbmRleC5cbiAgICogVGhpcyBpcyBuZWNlc3NhcnkgYmVjYXVzZSBhdCBpbmRleCAwLCB3aGVuIHlvdSBjYWxsIHByZXYgYWdhaW4sIHlvdSdsbCBnbyB0byB0aGUgbGFzdCBpbWFnZS5cbiAgICogVGhhdCBoYXBwZW5zIGJlY2F1c2UgYWxsIG1vZGFsIGltYWdlcyBhcmUgc2hvd24gbGlrZSBpbiBhIGNpcmNsZS5cbiAgICovXG4gIHByaXZhdGUgZ2V0UHJldkltYWdlKCk6IEludGVybmFsTGliSW1hZ2Uge1xuICAgIGlmICghdGhpcy5jdXJyZW50SW1hZ2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGN1cnJlbnRJbWFnZSBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgY3VycmVudEluZGV4OiBudW1iZXIgPSBnZXRJbmRleCh0aGlzLmN1cnJlbnRJbWFnZSwgdGhpcy5pbWFnZXMpO1xuICAgIGxldCBuZXdJbmRleCA9IDA7XG4gICAgaWYgKGN1cnJlbnRJbmRleCA+IDAgJiYgY3VycmVudEluZGV4IDw9IHRoaXMuaW1hZ2VzLmxlbmd0aCAtIDEpIHtcbiAgICAgIG5ld0luZGV4ID0gY3VycmVudEluZGV4IC0gMTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3SW5kZXggPSB0aGlzLmltYWdlcy5sZW5ndGggLSAxOyAvLyBzdGFydCBmcm9tIHRoZSBsYXN0IGluZGV4XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmltYWdlc1tuZXdJbmRleF0gYXMgSW50ZXJuYWxMaWJJbWFnZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcml2YXRlIG1ldGhvZCB0byBidWlsZCBhIHRleHQgZGVzY3JpcHRpb24uXG4gICAqIFRoaXMgaXMgdXNlZCBhbHNvIHRvIGNyZWF0ZSB0aXRsZXMuXG4gICAqIEBwYXJhbSBJbWFnZSBpbWFnZSB0byBnZXQgaXRzIGRlc2NyaXB0aW9uLiBJZiBub3QgcHJvdmlkZWQgaXQgd2lsbCBiZSB0aGUgY3VycmVudCBpbWFnZS5cbiAgICogQHBhcmFtIGJvb2xlYW4gaW1hZ2VXaXRob3V0RGVzY3JpcHRpb24gaXMgYSBib29sZWFuIHRoYXQgaXQncyB0cnVlIGlmIHRoZSBpbWFnZSBoYXNuJ3QgYSAnbW9kYWwnIGRlc2NyaXB0aW9uLlxuICAgKiBAcmV0dXJucyBTdHJpbmcgZGVzY3JpcHRpb24gYnVpbHQgY29uY2F0ZW5hdGluZyBpbWFnZSBmaWVsZHMgd2l0aCBhIHNwZWNpZmljIGxvZ2ljLlxuICAgKi9cbiAgcHJpdmF0ZSBidWlsZFRleHREZXNjcmlwdGlvbihpbWFnZTogSW1hZ2UgfCB1bmRlZmluZWQsIGltYWdlV2l0aG91dERlc2NyaXB0aW9uOiBib29sZWFuKTogc3RyaW5nIHtcbiAgICBpZiAodGhpcy5pZCA9PT0gbnVsbCB8fCB0aGlzLmlkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGlkIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBjb25zdCBsaWJDb25maWc6IExpYkNvbmZpZyB8IHVuZGVmaW5lZCA9IHRoaXMuY29uZmlnU2VydmljZS5nZXRDb25maWcodGhpcy5pZCk7XG4gICAgaWYgKCFsaWJDb25maWcgfHwgIWxpYkNvbmZpZy5jYXJvdXNlbEltYWdlQ29uZmlnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBsaWJDb25maWcgYW5kIGNhcm91c2VsSW1hZ2VDb25maWcgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IGNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsOiBDYXJvdXNlbEltYWdlQ29uZmlnIHwgdW5kZWZpbmVkID0gbGliQ29uZmlnLmNhcm91c2VsSW1hZ2VDb25maWc7XG4gICAgaWYgKCFjb25maWdDdXJyZW50SW1hZ2VDYXJvdXNlbCB8fCAhY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWwuZGVzY3JpcHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRGVzY3JpcHRpb24gaW5wdXQgbXVzdCBiZSBhIHZhbGlkIG9iamVjdCBpbXBsZW1lbnRpbmcgdGhlIERlc2NyaXB0aW9uIGludGVyZmFjZScpO1xuICAgIH1cbiAgICBpZiAoIWltYWdlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBpbWFnZSBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG5cbiAgICAvLyBJZiBjdXN0b21GdWxsRGVzY3JpcHRpb24gdXNlIGl0LCBvdGhlcndpc2UgcHJvY2VlZCB0byBidWlsZCBhIGRlc2NyaXB0aW9uXG4gICAgaWYgKGNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsLmRlc2NyaXB0aW9uLmN1c3RvbUZ1bGxEZXNjcmlwdGlvbiAmJiBjb25maWdDdXJyZW50SW1hZ2VDYXJvdXNlbC5kZXNjcmlwdGlvbi5jdXN0b21GdWxsRGVzY3JpcHRpb24gIT09ICcnKSB7XG4gICAgICByZXR1cm4gY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWwuZGVzY3JpcHRpb24uY3VzdG9tRnVsbERlc2NyaXB0aW9uO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnJlbnRJbmRleDogbnVtYmVyID0gZ2V0SW5kZXgoaW1hZ2UsIHRoaXMuaW1hZ2VzKTtcbiAgICAvLyBJZiB0aGUgY3VycmVudCBpbWFnZSBoYXNuJ3QgYSBkZXNjcmlwdGlvbixcbiAgICAvLyBwcmV2ZW50IHRvIHdyaXRlIHRoZSAnIC0gJyAob3IgdGhpcy5kZXNjcmlwdGlvbi5iZWZvcmVUZXh0RGVzY3JpcHRpb24pXG5cbiAgICBjb25zdCBwcmV2RGVzY3JpcHRpb246IHN0cmluZyA9IGNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsLmRlc2NyaXB0aW9uLmltYWdlVGV4dCA/IGNvbmZpZ0N1cnJlbnRJbWFnZUNhcm91c2VsLmRlc2NyaXB0aW9uLmltYWdlVGV4dCA6ICcnO1xuICAgIGNvbnN0IG1pZFNlcGFyYXRvcjogc3RyaW5nID0gY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWwuZGVzY3JpcHRpb24ubnVtYmVyU2VwYXJhdG9yID8gY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWwuZGVzY3JpcHRpb24ubnVtYmVyU2VwYXJhdG9yIDogJyc7XG4gICAgY29uc3QgbWlkZGxlRGVzY3JpcHRpb246IHN0cmluZyA9IGN1cnJlbnRJbmRleCArIDEgKyBtaWRTZXBhcmF0b3IgKyB0aGlzLmltYWdlcy5sZW5ndGg7XG5cbiAgICBpZiAoaW1hZ2VXaXRob3V0RGVzY3JpcHRpb24pIHtcbiAgICAgIHJldHVybiBwcmV2RGVzY3JpcHRpb24gKyBtaWRkbGVEZXNjcmlwdGlvbjtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJySW1nRGVzY3JpcHRpb246IHN0cmluZyA9IGltYWdlLm1vZGFsICYmIGltYWdlLm1vZGFsLmRlc2NyaXB0aW9uID8gaW1hZ2UubW9kYWwuZGVzY3JpcHRpb24gOiAnJztcbiAgICBjb25zdCBlbmREZXNjcmlwdGlvbjogc3RyaW5nID0gY29uZmlnQ3VycmVudEltYWdlQ2Fyb3VzZWwuZGVzY3JpcHRpb24uYmVmb3JlVGV4dERlc2NyaXB0aW9uICsgY3VyckltZ0Rlc2NyaXB0aW9uO1xuICAgIHJldHVybiBwcmV2RGVzY3JpcHRpb24gKyBtaWRkbGVEZXNjcmlwdGlvbiArIGVuZERlc2NyaXB0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIHVwZGF0ZSBib3RoIGBpc0ZpcnN0SW1hZ2VgIGFuZCBgaXNMYXN0SW1hZ2VgIGJhc2VkIG9uXG4gICAqIHRoZSBpbmRleCBvZiB0aGUgY3VycmVudCBpbWFnZS5cbiAgICogQHBhcmFtIG51bWJlciBjdXJyZW50SW5kZXggaXMgdGhlIGluZGV4IG9mIHRoZSBjdXJyZW50IGltYWdlXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZUJvdW5kYXJpZXMoY3VycmVudEluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pbWFnZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICB0aGlzLmlzRmlyc3RJbWFnZSA9IHRydWU7XG4gICAgICB0aGlzLmlzTGFzdEltYWdlID0gdHJ1ZTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgc3dpdGNoIChjdXJyZW50SW5kZXgpIHtcbiAgICAgIGNhc2UgMDpcbiAgICAgICAgLy8gZXhlY3V0ZSB0aGlzIG9ubHkgaWYgaW5maW5pdGUgc2xpZGluZyBpcyBkaXNhYmxlZFxuICAgICAgICB0aGlzLmlzRmlyc3RJbWFnZSA9IHRydWU7XG4gICAgICAgIHRoaXMuaXNMYXN0SW1hZ2UgPSBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIHRoaXMuaW1hZ2VzLmxlbmd0aCAtIDE6XG4gICAgICAgIC8vIGV4ZWN1dGUgdGhpcyBvbmx5IGlmIGluZmluaXRlIHNsaWRpbmcgaXMgZGlzYWJsZWRcbiAgICAgICAgdGhpcy5pc0ZpcnN0SW1hZ2UgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc0xhc3RJbWFnZSA9IHRydWU7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhpcy5pc0ZpcnN0SW1hZ2UgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5pc0xhc3RJbWFnZSA9IGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJpdmF0ZSBtZXRob2QgdG8gbWFuYWdlIGJvdW5kYXJ5IGFycm93cyBhbmQgc2xpZGluZy5cbiAgICogVGhpcyBpcyBiYXNlZCBvbiB0aGUgc2xpZGVDb25maWcgaW5wdXQgdG8gZW5hYmxlL2Rpc2FibGUgJ2luZmluaXRlIHNsaWRpbmcnLlxuICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4IG9mIHRoZSB2aXNpYmxlIGltYWdlXG4gICAqL1xuICBwcml2YXRlIG1hbmFnZVNsaWRlQ29uZmlnKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmlkID09PSBudWxsIHx8IHRoaXMuaWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gaWQgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IGxpYkNvbmZpZzogTGliQ29uZmlnIHwgdW5kZWZpbmVkID0gdGhpcy5jb25maWdTZXJ2aWNlLmdldENvbmZpZyh0aGlzLmlkKTtcbiAgICBpZiAoIWxpYkNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gbGliQ29uZmlnIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuY3VycmVudEltYWdlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBjdXJyZW50SW1hZ2UgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGxldCBpbmRleDogbnVtYmVyO1xuICAgIHRyeSB7XG4gICAgICBpbmRleCA9IGdldEluZGV4KHRoaXMuY3VycmVudEltYWdlLCB0aGlzLmltYWdlcyk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdDYW5ub3QgZ2V0IHRoZSBjdXJyZW50IGltYWdlIGluZGV4IGluIGN1cnJlbnQtaW1hZ2UnKTtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG5cbiAgICBpZiAobGliQ29uZmlnLmNhcm91c2VsU2xpZGVJbmZpbml0ZSA9PT0gdHJ1ZSkge1xuICAgICAgLy8gZW5hYmxlIGluZmluaXRlIHNsaWRpbmdcbiAgICAgIHRoaXMuaXNGaXJzdEltYWdlID0gZmFsc2U7XG4gICAgICB0aGlzLmlzTGFzdEltYWdlID0gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuaGFuZGxlQm91bmRhcmllcyhpbmRleCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIGVtaXQgZXZlbnRzIHdoZW4gZWl0aGVyIHRoZSBsYXN0IG9yIHRoZSBmaXJzdCBpbWFnZSBhcmUgdmlzaWJsZS5cbiAgICogQHBhcmFtIGFjdGlvbiBFbnVtIG9mIHR5cGUgQWN0aW9uIHRoYXQgcmVwcmVzZW50cyB0aGUgc291cmNlIG9mIHRoZSBldmVudCB0aGF0IGNoYW5nZWQgdGhlXG4gICAqICBjdXJyZW50IGltYWdlIHRvIHRoZSBmaXJzdCBvbmUgb3IgdGhlIGxhc3Qgb25lLlxuICAgKiBAcGFyYW0gaW5kZXhUb0NoZWNrIGlzIHRoZSBpbmRleCBudW1iZXIgb2YgdGhlIGltYWdlICh0aGUgZmlyc3Qgb3IgdGhlIGxhc3Qgb25lKS5cbiAgICovXG4gIHByaXZhdGUgZW1pdEJvdW5kYXJ5RXZlbnQoYWN0aW9uOiBBY3Rpb24sIGluZGV4VG9DaGVjazogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaWQgPT09IG51bGwgfHwgdGhpcy5pZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIHRvIGVtaXQgZmlyc3QvbGFzdCBldmVudFxuICAgIHN3aXRjaCAoaW5kZXhUb0NoZWNrKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHRoaXMuZmlyc3RJbWFnZS5lbWl0KG5ldyBJbWFnZUV2ZW50KHRoaXMuaWQsIGFjdGlvbiwgdHJ1ZSkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgdGhpcy5pbWFnZXMubGVuZ3RoIC0gMTpcbiAgICAgICAgdGhpcy5sYXN0SW1hZ2UuZW1pdChuZXcgSW1hZ2VFdmVudCh0aGlzLmlkLCBhY3Rpb24sIHRydWUpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIGNoZWNrIGlmIG5leHQvcHJldiBhY3Rpb25zIHNob3VsZCBiZSBibG9ja2VkLlxuICAgKiBJdCBjaGVja3MgaWYgY2Fyb3VzZWxTbGlkZUluZmluaXRlID09PSBmYWxzZSBhbmQgaWYgdGhlIGltYWdlIGluZGV4IGlzIGVxdWFscyB0byB0aGUgaW5wdXQgcGFyYW1ldGVyLlxuICAgKiBJZiB5ZXMsIGl0IHJldHVybnMgdHJ1ZSB0byBzYXkgdGhhdCBzbGlkaW5nIHNob3VsZCBiZSBibG9ja2VkLCBvdGhlcndpc2Ugbm90LlxuICAgKiBAcGFyYW0gbnVtYmVyIGJvdW5kYXJ5SW5kZXggdGhhdCBjb3VsZCBiZSBlaXRoZXIgdGhlIGJlZ2lubmluZyBpbmRleCAoMCkgb3IgdGhlIGxhc3QgaW5kZXhcbiAgICogIG9mIGltYWdlcyAodGhpcy5pbWFnZXMubGVuZ3RoIC0gMSkuXG4gICAqIEByZXR1cm5zIGJvb2xlYW4gdHJ1ZSBpZiBjYXJvdXNlbFNsaWRlSW5maW5pdGUgPT09IGZhbHNlIGFuZCB0aGUgY3VycmVudCBpbmRleCBpc1xuICAgKiAgZWl0aGVyIHRoZSBmaXJzdCBvciB0aGUgbGFzdCBvbmUuXG4gICAqL1xuICBwcml2YXRlIGlzUHJldmVudFNsaWRpbmcoYm91bmRhcnlJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuaWQgPT09IG51bGwgfHwgdGhpcy5pZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBpZCBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgbGliQ29uZmlnOiBMaWJDb25maWcgfCB1bmRlZmluZWQgPSB0aGlzLmNvbmZpZ1NlcnZpY2UuZ2V0Q29uZmlnKHRoaXMuaWQpO1xuICAgIGlmICghbGliQ29uZmlnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBsaWJDb25maWcgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGlmICghdGhpcy5jdXJyZW50SW1hZ2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGN1cnJlbnRJbWFnZSBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgcmV0dXJuICFsaWJDb25maWcuY2Fyb3VzZWxTbGlkZUluZmluaXRlICYmIGdldEluZGV4KHRoaXMuY3VycmVudEltYWdlLCB0aGlzLmltYWdlcykgPT09IGJvdW5kYXJ5SW5kZXg7XG4gIH1cbn1cbiIsIjxtYWluIGlkPVwiY2Fyb3VzZWwtY29udGFpbmVyXCJcbiAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiYWNjZXNzaWJpbGl0eUNvbmZpZz8uY2Fyb3VzZWxDb250YWluZXJBcmlhTGFiZWxcIlxuICAgICAgW3RpdGxlXT1cImFjY2Vzc2liaWxpdHlDb25maWc/LmNhcm91c2VsQ29udGFpbmVyVGl0bGVcIlxuICAgICAga3NNYXhTaXplIFttYXhTaXplQ29uZmlnXT1cInttYXhXaWR0aDogY2Fyb3VzZWxDb25maWc/Lm1heFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heEhlaWdodDogJyd9XCI+XG5cblxuICA8IS0tIFdvcmthcm91bmQgdG8gc3VwcG9ydCAyIG5nLWNvbnRlbnQgaW4gdGhlIHNhbWUgdGVtcGxhdGUgaW4gMiBuZ0lmIChodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9hbmd1bGFyL2lzc3Vlcy8yMjk3MikgLS0+XG4gIDxuZy10ZW1wbGF0ZSAjY29udGVudD48bmctY29udGVudD48L25nLWNvbnRlbnQ+PC9uZy10ZW1wbGF0ZT5cblxuICA8ZmlndXJlIGNsYXNzPVwiY3VycmVudC1maWd1cmVcIiAqbmdJZj1cImN1cnJlbnRJbWFnZSAmJiBjdXJyZW50SW1hZ2UubW9kYWxcIlxuICAgICAgICAgIGtzU2l6ZSBbc2l6ZUNvbmZpZ109XCJ7d2lkdGg6IGNhcm91c2VsQ29uZmlnPy5tYXhXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAnJ31cIj5cblxuICAgIDxhIGNsYXNzPVwibmF2LWxlZnRcIiAqbmdJZj1cImNhcm91c2VsQ29uZmlnPy5zaG93QXJyb3dzXCJcbiAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImFjY2Vzc2liaWxpdHlDb25maWc/LmNhcm91c2VsUHJldkltYWdlQXJpYUxhYmVsXCJcbiAgICAgICBbdGFiSW5kZXhdPVwiaXNMYXN0SW1hZ2UgJiYgIWNhcm91c2VsU2xpZGVJbmZpbml0ZSA/IC0xIDogMFwiIHJvbGU9XCJidXR0b25cIlxuICAgICAgIChjbGljayk9XCJvbk5hdmlnYXRpb25FdmVudCgnbGVmdCcsICRldmVudCwgY2xpY2tBY3Rpb24pXCIgKGtleXVwKT1cIm9uTmF2aWdhdGlvbkV2ZW50KCdsZWZ0JywgJGV2ZW50LCBrZXlib2FyZEFjdGlvbilcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnNpZGUge3soaXNGaXJzdEltYWdlICYmICFjYXJvdXNlbFNsaWRlSW5maW5pdGUpIHx8ICFjYXJvdXNlbENvbmZpZy5zaG93QXJyb3dzID8gJ2VtcHR5LWFycm93LWltYWdlJyA6ICdsZWZ0LWFycm93LWltYWdlJ319XCJcbiAgICAgICAgICAgYXJpYS1oaWRkZW49XCJ0cnVlXCJcbiAgICAgICAgICAgW3RpdGxlXT1cImFjY2Vzc2liaWxpdHlDb25maWc/LmNhcm91c2VsUHJldkltYWdlVGl0bGVcIj48L2Rpdj5cbiAgICA8L2E+XG5cbiAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiY29udGVudFwiPjwvbmctY29udGFpbmVyPlxuICAgIDxwaWN0dXJlIGNsYXNzPVwiY3VycmVudC1pbWFnZVwiIGtzTWF4U2l6ZSBbbWF4U2l6ZUNvbmZpZ109XCJ7bWF4V2lkdGg6IGNhcm91c2VsQ29uZmlnPy5tYXhXaWR0aCxcbiAgICAgIG1heEhlaWdodDogY2Fyb3VzZWxDb25maWc/Lm1heEhlaWdodH1cIj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IHNvdXJjZSBvZiBjdXJyZW50SW1hZ2UubW9kYWw/LnNvdXJjZXNcIj5cbiAgICAgICAgPHNvdXJjZSBbbWVkaWFdPVwic291cmNlLm1lZGlhXCIgW3NyY3NldF09XCJzb3VyY2Uuc3Jjc2V0XCI+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDxpbWcgW2lkXT1cImN1cnJlbnRJbWFnZS5pZFwiXG4gICAgICAgICAgW2xvYWRpbmddPVwiY3VycmVudEltYWdlLmxvYWRpbmdcIlxuICAgICAgICAgIFthdHRyLmZldGNocHJpb3JpdHldPVwiY3VycmVudEltYWdlLmZldGNocHJpb3JpdHlcIlxuICAgICAgICAgIFtzdHlsZS5vYmplY3QtZml0XT1cImNhcm91c2VsQ29uZmlnPy5vYmplY3RGaXRcIlxuICAgICAgICAgIGtzTWF4U2l6ZSBbbWF4U2l6ZUNvbmZpZ109XCJ7bWF4V2lkdGg6IGNhcm91c2VsQ29uZmlnPy5tYXhXaWR0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heEhlaWdodDogY2Fyb3VzZWxDb25maWc/Lm1heEhlaWdodH1cIlxuICAgICAgICAgIFtzcmNdPVwiY3VycmVudEltYWdlLm1vZGFsLmltZ1wiXG4gICAgICAgICAga3NGYWxsYmFja0ltYWdlIFtmYWxsYmFja0ltZ109XCJjdXJyZW50SW1hZ2UubW9kYWwuZmFsbGJhY2tJbWdcIlxuICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiY3VycmVudEltYWdlLm1vZGFsLmFyaWFMYWJlbFwiXG4gICAgICAgICAgW3RpdGxlXT1cIihjdXJyZW50SW1hZ2UubW9kYWwudGl0bGUgfHwgY3VycmVudEltYWdlLm1vZGFsLnRpdGxlID09PSAnJykgPyBjdXJyZW50SW1hZ2UubW9kYWwudGl0bGUgOiBnZXRUaXRsZVRvRGlzcGxheSgpXCJcbiAgICAgICAgICBhbHQ9XCJ7e2N1cnJlbnRJbWFnZS5tb2RhbC5hbHQgPyBjdXJyZW50SW1hZ2UubW9kYWwuYWx0IDogZ2V0QWx0RGVzY3JpcHRpb25CeUltYWdlKCl9fVwiXG4gICAgICAgICAgW3RhYkluZGV4XT1cIjBcIiByb2xlPVwiaW1nXCJcbiAgICAgICAgICAoY2xpY2spPVwib25DbGlja0N1cnJlbnRJbWFnZSgpXCJcbiAgICAgICAgICAoc3dpcGVsZWZ0KT1cInN3aXBlKCRldmVudC50eXBlKVwiXG4gICAgICAgICAgKHN3aXBlcmlnaHQpPVwic3dpcGUoJGV2ZW50LnR5cGUpXCIvPlxuICAgIDwvcGljdHVyZT5cbiAgICA8ZmlnY2FwdGlvbiAqbmdJZj1cImdldERlc2NyaXB0aW9uVG9EaXNwbGF5KCkgIT09ICcnXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImRlc2NyaXB0aW9uXCJcbiAgICAgICAgICAgICAgICBrc0Rlc2NyaXB0aW9uIFtkZXNjcmlwdGlvbl09XCJjYXJvdXNlbEltYWdlQ29uZmlnPy5kZXNjcmlwdGlvblwiXG4gICAgICAgICAgICAgICAgW2lubmVySFRNTF09XCJnZXREZXNjcmlwdGlvblRvRGlzcGxheSgpXCI+PC9maWdjYXB0aW9uPlxuXG4gICAgPGEgY2xhc3M9XCJuYXYtcmlnaHRcIiAqbmdJZj1cImNhcm91c2VsQ29uZmlnPy5zaG93QXJyb3dzXCJcbiAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImFjY2Vzc2liaWxpdHlDb25maWc/LmNhcm91c2VsTmV4dEltYWdlQXJpYUxhYmVsXCJcbiAgICAgICBbdGFiSW5kZXhdPVwiaXNMYXN0SW1hZ2UgJiYgIWNhcm91c2VsU2xpZGVJbmZpbml0ZSA/IC0xIDogMFwiIHJvbGU9XCJidXR0b25cIlxuICAgICAgIChjbGljayk9XCJvbk5hdmlnYXRpb25FdmVudCgncmlnaHQnLCAkZXZlbnQsIGNsaWNrQWN0aW9uKVwiIChrZXl1cCk9XCJvbk5hdmlnYXRpb25FdmVudCgncmlnaHQnLCAkZXZlbnQsIGtleWJvYXJkQWN0aW9uKVwiPlxuICAgICAgPGRpdiBjbGFzcz1cImluc2lkZSB7eyhpc0xhc3RJbWFnZSAmJiAhY2Fyb3VzZWxTbGlkZUluZmluaXRlKSB8fCAhY2Fyb3VzZWxDb25maWcuc2hvd0Fycm93cyA/ICdlbXB0eS1hcnJvdy1pbWFnZScgOiAncmlnaHQtYXJyb3ctaW1hZ2UnfX1cIlxuICAgICAgICAgICBhcmlhLWhpZGRlbj1cInRydWVcIlxuICAgICAgICAgICBbdGl0bGVdPVwiYWNjZXNzaWJpbGl0eUNvbmZpZz8uY2Fyb3VzZWxOZXh0SW1hZ2VUaXRsZVwiPjwvZGl2PlxuICAgIDwvYT5cblxuICAgIDxkaXYgaWQ9XCJkb3RzXCI+XG4gICAgICA8a3MtZG90cyBbaWRdPVwiaWRcIlxuICAgICAgICAgICAgICAgW2N1cnJlbnRJbWFnZV09XCJjdXJyZW50SW1hZ2VcIlxuICAgICAgICAgICAgICAgW2ltYWdlc109XCJpbWFnZXNcIlxuICAgICAgICAgICAgICAgW2RvdHNDb25maWddPVwiY2Fyb3VzZWxEb3RzQ29uZmlnXCJcbiAgICAgICAgICAgICAgIChjbGlja0RvdCk9XCJvbkNsaWNrRG90KCRldmVudClcIj48L2tzLWRvdHM+XG4gICAgPC9kaXY+XG5cbiAgPC9maWd1cmU+XG5cbjwvbWFpbj5cblxuPGtzLWNhcm91c2VsLXByZXZpZXdzIFtpZF09XCJpZFwiXG4gICAgICAgICAgICAgICAgICAgICAgW2ltYWdlc109XCJpbWFnZXNcIlxuICAgICAgICAgICAgICAgICAgICAgIFtjdXJyZW50SW1hZ2VdPVwiY3VycmVudEltYWdlXCJcbiAgICAgICAgICAgICAgICAgICAgICAoY2xpY2tQcmV2aWV3KT1cIm9uQ2xpY2tQcmV2aWV3KCRldmVudClcIj48L2tzLWNhcm91c2VsLXByZXZpZXdzPlxuIl19
|