@glowhop/angular-tour 1.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/.npmignore +2 -0
- package/CHANGELOG.md +12 -0
- package/LICENSE +22 -0
- package/README.md +33 -0
- package/config/index.d.ts +5 -0
- package/config/package.json +3 -0
- package/config/public-api.d.ts +37 -0
- package/esm2022/config/glowhop-angular-tour-config.mjs +5 -0
- package/esm2022/config/public-api.mjs +25 -0
- package/esm2022/glowhop-angular-tour.mjs +5 -0
- package/esm2022/lib/components/default-tour.mjs +66 -0
- package/esm2022/lib/components/tour-components.mjs +624 -0
- package/esm2022/lib/glow-tour.mjs +10 -0
- package/esm2022/public-api.mjs +4 -0
- package/fesm2022/glowhop-angular-tour-config.mjs +32 -0
- package/fesm2022/glowhop-angular-tour-config.mjs.map +1 -0
- package/fesm2022/glowhop-angular-tour.mjs +704 -0
- package/fesm2022/glowhop-angular-tour.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/components/default-tour.d.ts +11 -0
- package/lib/components/tour-components.d.ts +173 -0
- package/lib/glow-tour.d.ts +20 -0
- package/package.json +51 -0
- package/public-api.d.ts +6 -0
|
@@ -0,0 +1,624 @@
|
|
|
1
|
+
import { NgTemplateOutlet } from "@angular/common";
|
|
2
|
+
import { booleanAttribute, Component, computed, DestroyRef, Directive, ElementRef, effect, Injectable, InjectionToken, Injector, Input, inject, signal, TemplateRef, ViewChild, } from "@angular/core";
|
|
3
|
+
import { connectGlowTourRoot, OVERLAY_IDLE_ATTRIBUTES, OVERLAY_IDLE_STYLE, OVERLAY_PATH_IDLE_ATTRIBUTES, POINTER_IDLE_ATTRIBUTES, POINTER_IDLE_STYLE, POPOVER_IDLE_ATTRIBUTES, POPOVER_IDLE_STYLE, styleRecordToCssText, } from "@glowhop/core-tour/adapter";
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
const OVERLAY_IDLE_STYLE_TEXT = styleRecordToCssText(OVERLAY_IDLE_STYLE);
|
|
6
|
+
const POINTER_IDLE_STYLE_TEXT = styleRecordToCssText(POINTER_IDLE_STYLE);
|
|
7
|
+
const POPOVER_IDLE_STYLE_TEXT = styleRecordToCssText(POPOVER_IDLE_STYLE);
|
|
8
|
+
const DEFAULT_POINTER_DIRECTION_CONTENT = {
|
|
9
|
+
bottom: "👇",
|
|
10
|
+
left: "👈",
|
|
11
|
+
right: "👉",
|
|
12
|
+
top: "👆",
|
|
13
|
+
};
|
|
14
|
+
const POINTER_DIRECTIONS = ["top", "bottom", "left", "right"];
|
|
15
|
+
class GlowTourScope {
|
|
16
|
+
binding = signal(null);
|
|
17
|
+
tour = signal(null);
|
|
18
|
+
snapshot = signal(null);
|
|
19
|
+
state = this.snapshot.asReadonly();
|
|
20
|
+
constructor() {
|
|
21
|
+
effect((onCleanup) => {
|
|
22
|
+
const tour = this.tour();
|
|
23
|
+
if (!tour) {
|
|
24
|
+
this.snapshot.set(null);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
this.snapshot.set(tour.state.get());
|
|
28
|
+
onCleanup(tour.state.subscribe((state) => this.snapshot.set(state)));
|
|
29
|
+
}, { allowSignalWrites: true });
|
|
30
|
+
}
|
|
31
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourScope, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
32
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourScope });
|
|
33
|
+
}
|
|
34
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourScope, decorators: [{
|
|
35
|
+
type: Injectable
|
|
36
|
+
}], ctorParameters: () => [] });
|
|
37
|
+
const GLOW_TOUR_SCOPE = new InjectionToken("GlowTourScope");
|
|
38
|
+
function useTourScope() {
|
|
39
|
+
const scope = inject(GLOW_TOUR_SCOPE, { optional: true });
|
|
40
|
+
if (!scope) {
|
|
41
|
+
throw new Error('GlowTour components must be rendered inside <glow-tour-root [tour]="...">.');
|
|
42
|
+
}
|
|
43
|
+
return scope;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Injects the tour state signal into a component.
|
|
47
|
+
* Must be called within a GlowTourRoot component context.
|
|
48
|
+
* @returns A signal containing the current tour state or null.
|
|
49
|
+
*/
|
|
50
|
+
export function injectGlowTour() {
|
|
51
|
+
return useTourScope().state;
|
|
52
|
+
}
|
|
53
|
+
class GlowTourReactiveComponent {
|
|
54
|
+
scope = useTourScope();
|
|
55
|
+
snapshot = this.scope.state;
|
|
56
|
+
step = computed(() => this.snapshot()?.currentStep?.currentProps ?? null);
|
|
57
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourReactiveComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
58
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: GlowTourReactiveComponent, ngImport: i0 });
|
|
59
|
+
}
|
|
60
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourReactiveComponent, decorators: [{
|
|
61
|
+
type: Directive
|
|
62
|
+
}] });
|
|
63
|
+
/** Root container component for GlowTour.js. Provides tour context and manages the root binding. */
|
|
64
|
+
export class GlowTourRoot {
|
|
65
|
+
/** The tour controller instance to display. */
|
|
66
|
+
tour;
|
|
67
|
+
/** Optional prefix for generated HTML IDs. */
|
|
68
|
+
idPrefix;
|
|
69
|
+
element = inject((ElementRef));
|
|
70
|
+
scope = inject(GlowTourScope);
|
|
71
|
+
active = null;
|
|
72
|
+
initialized = false;
|
|
73
|
+
ngOnChanges() {
|
|
74
|
+
if (this.initialized)
|
|
75
|
+
this.reconcile();
|
|
76
|
+
}
|
|
77
|
+
ngOnInit() {
|
|
78
|
+
if (!this.tour) {
|
|
79
|
+
throw new Error("GlowTourRoot requires a tour input.");
|
|
80
|
+
}
|
|
81
|
+
this.initialized = true;
|
|
82
|
+
this.reconcile();
|
|
83
|
+
}
|
|
84
|
+
ngOnDestroy() {
|
|
85
|
+
this.release();
|
|
86
|
+
}
|
|
87
|
+
reconcile() {
|
|
88
|
+
const root = this.element.nativeElement;
|
|
89
|
+
const tour = this.tour;
|
|
90
|
+
const idPrefix = this.idPrefix;
|
|
91
|
+
this.scope.tour.set(tour);
|
|
92
|
+
const current = this.active;
|
|
93
|
+
if (current !== null &&
|
|
94
|
+
current.root === root &&
|
|
95
|
+
current.tour === tour &&
|
|
96
|
+
current.idPrefix === idPrefix) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
this.release();
|
|
100
|
+
const binding = connectGlowTourRoot(tour, {
|
|
101
|
+
idPrefix,
|
|
102
|
+
root,
|
|
103
|
+
});
|
|
104
|
+
const active = { binding, idPrefix, root, tour };
|
|
105
|
+
this.active = active;
|
|
106
|
+
this.scope.binding.set(binding);
|
|
107
|
+
}
|
|
108
|
+
release() {
|
|
109
|
+
const active = this.active;
|
|
110
|
+
if (!active)
|
|
111
|
+
return;
|
|
112
|
+
this.active = null;
|
|
113
|
+
active.binding.release();
|
|
114
|
+
if (this.scope.binding() === active.binding)
|
|
115
|
+
this.scope.binding.set(null);
|
|
116
|
+
}
|
|
117
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourRoot, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
118
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GlowTourRoot, isStandalone: true, selector: "glow-tour-root", inputs: { tour: "tour", idPrefix: "idPrefix" }, host: { attributes: { "data-glow-tour-root": "" } }, providers: [GlowTourScope, { provide: GLOW_TOUR_SCOPE, useExisting: GlowTourScope }], usesOnChanges: true, ngImport: i0, template: "<ng-content />", isInline: true });
|
|
119
|
+
}
|
|
120
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourRoot, decorators: [{
|
|
121
|
+
type: Component,
|
|
122
|
+
args: [{
|
|
123
|
+
selector: "glow-tour-root",
|
|
124
|
+
standalone: true,
|
|
125
|
+
host: { "data-glow-tour-root": "" },
|
|
126
|
+
providers: [GlowTourScope, { provide: GLOW_TOUR_SCOPE, useExisting: GlowTourScope }],
|
|
127
|
+
template: "<ng-content />",
|
|
128
|
+
}]
|
|
129
|
+
}], propDecorators: { tour: [{
|
|
130
|
+
type: Input,
|
|
131
|
+
args: [{ required: true }]
|
|
132
|
+
}], idPrefix: [{
|
|
133
|
+
type: Input
|
|
134
|
+
}] } });
|
|
135
|
+
/** Header component displaying the current step's title. */
|
|
136
|
+
export class GlowTourHeader extends GlowTourReactiveComponent {
|
|
137
|
+
titleTemplate = computed(() => {
|
|
138
|
+
const title = this.step()?.title;
|
|
139
|
+
return title instanceof TemplateRef ? title : null;
|
|
140
|
+
});
|
|
141
|
+
titleText = computed(() => {
|
|
142
|
+
const title = this.step()?.title;
|
|
143
|
+
return typeof title === "string" ? title : "";
|
|
144
|
+
});
|
|
145
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourHeader, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
146
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GlowTourHeader, isStandalone: true, selector: "glow-tour-header", usesInheritance: true, ngImport: i0, template: `
|
|
147
|
+
<header data-glow-tour-header [id]="scope.binding()?.ids?.title">
|
|
148
|
+
@if (titleTemplate()) {
|
|
149
|
+
<ng-container [ngTemplateOutlet]="titleTemplate()" />
|
|
150
|
+
} @else {
|
|
151
|
+
{{ titleText() }}
|
|
152
|
+
}
|
|
153
|
+
</header>
|
|
154
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
|
|
155
|
+
}
|
|
156
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourHeader, decorators: [{
|
|
157
|
+
type: Component,
|
|
158
|
+
args: [{
|
|
159
|
+
selector: "glow-tour-header",
|
|
160
|
+
standalone: true,
|
|
161
|
+
imports: [NgTemplateOutlet],
|
|
162
|
+
template: `
|
|
163
|
+
<header data-glow-tour-header [id]="scope.binding()?.ids?.title">
|
|
164
|
+
@if (titleTemplate()) {
|
|
165
|
+
<ng-container [ngTemplateOutlet]="titleTemplate()" />
|
|
166
|
+
} @else {
|
|
167
|
+
{{ titleText() }}
|
|
168
|
+
}
|
|
169
|
+
</header>
|
|
170
|
+
`,
|
|
171
|
+
}]
|
|
172
|
+
}] });
|
|
173
|
+
/** Content component displaying the current step's content with live region. */
|
|
174
|
+
export class GlowTourContent extends GlowTourReactiveComponent {
|
|
175
|
+
contentTemplate = computed(() => {
|
|
176
|
+
const content = this.step()?.content;
|
|
177
|
+
return content instanceof TemplateRef ? content : null;
|
|
178
|
+
});
|
|
179
|
+
contentText = computed(() => {
|
|
180
|
+
const content = this.step()?.content;
|
|
181
|
+
return typeof content === "string" ? content : "";
|
|
182
|
+
});
|
|
183
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourContent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
184
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GlowTourContent, isStandalone: true, selector: "glow-tour-content", usesInheritance: true, ngImport: i0, template: `
|
|
185
|
+
<div aria-live="polite" data-glow-tour-content [id]="scope.binding()?.ids?.description">
|
|
186
|
+
@if (contentTemplate()) {
|
|
187
|
+
<ng-container [ngTemplateOutlet]="contentTemplate()" />
|
|
188
|
+
} @else {
|
|
189
|
+
{{ contentText() }}
|
|
190
|
+
}
|
|
191
|
+
</div>
|
|
192
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
|
|
193
|
+
}
|
|
194
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourContent, decorators: [{
|
|
195
|
+
type: Component,
|
|
196
|
+
args: [{
|
|
197
|
+
selector: "glow-tour-content",
|
|
198
|
+
standalone: true,
|
|
199
|
+
imports: [NgTemplateOutlet],
|
|
200
|
+
template: `
|
|
201
|
+
<div aria-live="polite" data-glow-tour-content [id]="scope.binding()?.ids?.description">
|
|
202
|
+
@if (contentTemplate()) {
|
|
203
|
+
<ng-container [ngTemplateOutlet]="contentTemplate()" />
|
|
204
|
+
} @else {
|
|
205
|
+
{{ contentText() }}
|
|
206
|
+
}
|
|
207
|
+
</div>
|
|
208
|
+
`,
|
|
209
|
+
}]
|
|
210
|
+
}] });
|
|
211
|
+
/** Footer component containing action buttons. Conditionally rendered based on tour step configuration. */
|
|
212
|
+
export class GlowTourFooter extends GlowTourReactiveComponent {
|
|
213
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourFooter, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
214
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GlowTourFooter, isStandalone: true, selector: "glow-tour-footer", usesInheritance: true, ngImport: i0, template: `@if (!step()?.popover?.hideFooter) { <footer data-glow-tour-footer><ng-content /></footer> }`, isInline: true });
|
|
215
|
+
}
|
|
216
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourFooter, decorators: [{
|
|
217
|
+
type: Component,
|
|
218
|
+
args: [{
|
|
219
|
+
selector: "glow-tour-footer",
|
|
220
|
+
standalone: true,
|
|
221
|
+
template: `@if (!step()?.popover?.hideFooter) { <footer data-glow-tour-footer><ng-content /></footer> }`,
|
|
222
|
+
}]
|
|
223
|
+
}] });
|
|
224
|
+
class GlowTourBoundElement {
|
|
225
|
+
scope = useTourScope();
|
|
226
|
+
destroyRef = inject(DestroyRef);
|
|
227
|
+
injector = inject(Injector);
|
|
228
|
+
bind(element, bindElement) {
|
|
229
|
+
const cleanup = effect((onCleanup) => {
|
|
230
|
+
const binding = this.scope.binding();
|
|
231
|
+
if (binding)
|
|
232
|
+
onCleanup(bindElement(binding, element));
|
|
233
|
+
}, { injector: this.injector });
|
|
234
|
+
this.destroyRef.onDestroy(() => cleanup.destroy());
|
|
235
|
+
}
|
|
236
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourBoundElement, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
237
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: GlowTourBoundElement, ngImport: i0 });
|
|
238
|
+
}
|
|
239
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourBoundElement, decorators: [{
|
|
240
|
+
type: Directive
|
|
241
|
+
}] });
|
|
242
|
+
/** Popover component containing the tour content with accessibility attributes. */
|
|
243
|
+
export class GlowTourPopover extends GlowTourBoundElement {
|
|
244
|
+
element;
|
|
245
|
+
idleAriaHidden = POPOVER_IDLE_ATTRIBUTES["aria-hidden"];
|
|
246
|
+
idleInert = POPOVER_IDLE_ATTRIBUTES.inert;
|
|
247
|
+
idleStyle = POPOVER_IDLE_STYLE_TEXT;
|
|
248
|
+
ngOnInit() {
|
|
249
|
+
this.bind(this.element.nativeElement, (binding, element) => binding.bindPopover(element));
|
|
250
|
+
}
|
|
251
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourPopover, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
252
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GlowTourPopover, isStandalone: true, selector: "glow-tour-popover", viewQueries: [{ propertyName: "element", first: true, predicate: ["tourElement"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
253
|
+
<section #tourElement
|
|
254
|
+
[attr.aria-hidden]="idleAriaHidden"
|
|
255
|
+
data-glow-tour-popover
|
|
256
|
+
[attr.aria-describedby]="scope.binding()?.ids?.description"
|
|
257
|
+
[attr.aria-labelledby]="scope.binding()?.ids?.title"
|
|
258
|
+
[id]="scope.binding()?.ids?.popover"
|
|
259
|
+
[attr.inert]="idleInert"
|
|
260
|
+
role="dialog"
|
|
261
|
+
[style]="idleStyle"
|
|
262
|
+
tabindex="-1"
|
|
263
|
+
><ng-content /></section>
|
|
264
|
+
`, isInline: true });
|
|
265
|
+
}
|
|
266
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourPopover, decorators: [{
|
|
267
|
+
type: Component,
|
|
268
|
+
args: [{
|
|
269
|
+
selector: "glow-tour-popover",
|
|
270
|
+
standalone: true,
|
|
271
|
+
// The idle attributes/style come from imported `@glowhop/core-tour/adapter`
|
|
272
|
+
// constants, so ngc's AOT template analyzer (NG1010) cannot inline them as
|
|
273
|
+
// string-interpolated literals in the template. Bound via component fields
|
|
274
|
+
// instead; the values are still static, so server and client render
|
|
275
|
+
// byte-identical output.
|
|
276
|
+
template: `
|
|
277
|
+
<section #tourElement
|
|
278
|
+
[attr.aria-hidden]="idleAriaHidden"
|
|
279
|
+
data-glow-tour-popover
|
|
280
|
+
[attr.aria-describedby]="scope.binding()?.ids?.description"
|
|
281
|
+
[attr.aria-labelledby]="scope.binding()?.ids?.title"
|
|
282
|
+
[id]="scope.binding()?.ids?.popover"
|
|
283
|
+
[attr.inert]="idleInert"
|
|
284
|
+
role="dialog"
|
|
285
|
+
[style]="idleStyle"
|
|
286
|
+
tabindex="-1"
|
|
287
|
+
><ng-content /></section>
|
|
288
|
+
`,
|
|
289
|
+
}]
|
|
290
|
+
}], propDecorators: { element: [{
|
|
291
|
+
type: ViewChild,
|
|
292
|
+
args: ["tourElement", { static: true }]
|
|
293
|
+
}] } });
|
|
294
|
+
/** Pointer component displaying directional indicators pointing to the target element. */
|
|
295
|
+
export class GlowTourPointer extends GlowTourBoundElement {
|
|
296
|
+
element;
|
|
297
|
+
directionContentValue = signal(undefined);
|
|
298
|
+
idleAriaHidden = POINTER_IDLE_ATTRIBUTES["aria-hidden"];
|
|
299
|
+
idleStyle = POINTER_IDLE_STYLE_TEXT;
|
|
300
|
+
directions = POINTER_DIRECTIONS;
|
|
301
|
+
content = computed(() => ({
|
|
302
|
+
...DEFAULT_POINTER_DIRECTION_CONTENT,
|
|
303
|
+
...this.directionContentValue(),
|
|
304
|
+
}));
|
|
305
|
+
/** Optional custom content for each pointer direction. */
|
|
306
|
+
set directionContent(value) {
|
|
307
|
+
this.directionContentValue.set(value);
|
|
308
|
+
}
|
|
309
|
+
asTemplate(value) {
|
|
310
|
+
return value instanceof TemplateRef ? value : null;
|
|
311
|
+
}
|
|
312
|
+
ngOnInit() {
|
|
313
|
+
this.bind(this.element.nativeElement, (binding, element) => binding.bindPointer(element));
|
|
314
|
+
}
|
|
315
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourPointer, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
316
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GlowTourPointer, isStandalone: true, selector: "glow-tour-pointer", inputs: { directionContent: "directionContent" }, viewQueries: [{ propertyName: "element", first: true, predicate: ["tourElement"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
317
|
+
<div #tourElement data-glow-tour-pointer [attr.aria-hidden]="idleAriaHidden" [style]="idleStyle">
|
|
318
|
+
@for (direction of directions; track direction) {
|
|
319
|
+
<div [attr.data-glow-tour-pointer-direction]="direction">
|
|
320
|
+
@if (asTemplate(content()[direction]); as template) {
|
|
321
|
+
<ng-container [ngTemplateOutlet]="template" />
|
|
322
|
+
} @else {
|
|
323
|
+
{{ content()[direction] }}
|
|
324
|
+
}
|
|
325
|
+
</div>
|
|
326
|
+
}
|
|
327
|
+
</div>
|
|
328
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
|
|
329
|
+
}
|
|
330
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourPointer, decorators: [{
|
|
331
|
+
type: Component,
|
|
332
|
+
args: [{
|
|
333
|
+
selector: "glow-tour-pointer",
|
|
334
|
+
standalone: true,
|
|
335
|
+
imports: [NgTemplateOutlet],
|
|
336
|
+
template: `
|
|
337
|
+
<div #tourElement data-glow-tour-pointer [attr.aria-hidden]="idleAriaHidden" [style]="idleStyle">
|
|
338
|
+
@for (direction of directions; track direction) {
|
|
339
|
+
<div [attr.data-glow-tour-pointer-direction]="direction">
|
|
340
|
+
@if (asTemplate(content()[direction]); as template) {
|
|
341
|
+
<ng-container [ngTemplateOutlet]="template" />
|
|
342
|
+
} @else {
|
|
343
|
+
{{ content()[direction] }}
|
|
344
|
+
}
|
|
345
|
+
</div>
|
|
346
|
+
}
|
|
347
|
+
</div>
|
|
348
|
+
`,
|
|
349
|
+
}]
|
|
350
|
+
}], propDecorators: { element: [{
|
|
351
|
+
type: ViewChild,
|
|
352
|
+
args: ["tourElement", { static: true }]
|
|
353
|
+
}], directionContent: [{
|
|
354
|
+
type: Input
|
|
355
|
+
}] } });
|
|
356
|
+
/** Overlay component rendering a clipped SVG mask highlighting the target element. */
|
|
357
|
+
export class GlowTourOverlay extends GlowTourBoundElement {
|
|
358
|
+
element;
|
|
359
|
+
idleAriaHidden = OVERLAY_IDLE_ATTRIBUTES["aria-hidden"];
|
|
360
|
+
idleAllowInteraction = OVERLAY_IDLE_ATTRIBUTES["data-glow-tour-allow-interaction"];
|
|
361
|
+
idleInert = OVERLAY_IDLE_ATTRIBUTES.inert;
|
|
362
|
+
idleStyle = OVERLAY_IDLE_STYLE_TEXT;
|
|
363
|
+
idlePathCursor = OVERLAY_PATH_IDLE_ATTRIBUTES.cursor;
|
|
364
|
+
idlePathOpacity = OVERLAY_PATH_IDLE_ATTRIBUTES.opacity;
|
|
365
|
+
idlePathPointerEvents = OVERLAY_PATH_IDLE_ATTRIBUTES["pointer-events"];
|
|
366
|
+
ngOnInit() {
|
|
367
|
+
this.bind(this.element.nativeElement, (binding, element) => binding.bindOverlay(element));
|
|
368
|
+
}
|
|
369
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourOverlay, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
370
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GlowTourOverlay, isStandalone: true, selector: "glow-tour-overlay", viewQueries: [{ propertyName: "element", first: true, predicate: ["tourElement"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
371
|
+
<svg #tourElement
|
|
372
|
+
[attr.aria-hidden]="idleAriaHidden"
|
|
373
|
+
[attr.data-glow-tour-allow-interaction]="idleAllowInteraction"
|
|
374
|
+
data-glow-tour-overlay
|
|
375
|
+
focusable="false"
|
|
376
|
+
[attr.inert]="idleInert"
|
|
377
|
+
role="presentation"
|
|
378
|
+
[style]="idleStyle"
|
|
379
|
+
viewBox="0 0 0 0"
|
|
380
|
+
>
|
|
381
|
+
<path
|
|
382
|
+
[attr.cursor]="idlePathCursor"
|
|
383
|
+
data-glow-tour-overlay-path
|
|
384
|
+
fill-rule="evenodd"
|
|
385
|
+
[attr.opacity]="idlePathOpacity"
|
|
386
|
+
[attr.pointer-events]="idlePathPointerEvents"
|
|
387
|
+
/><ng-content />
|
|
388
|
+
</svg>
|
|
389
|
+
`, isInline: true });
|
|
390
|
+
}
|
|
391
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourOverlay, decorators: [{
|
|
392
|
+
type: Component,
|
|
393
|
+
args: [{
|
|
394
|
+
selector: "glow-tour-overlay",
|
|
395
|
+
standalone: true,
|
|
396
|
+
template: `
|
|
397
|
+
<svg #tourElement
|
|
398
|
+
[attr.aria-hidden]="idleAriaHidden"
|
|
399
|
+
[attr.data-glow-tour-allow-interaction]="idleAllowInteraction"
|
|
400
|
+
data-glow-tour-overlay
|
|
401
|
+
focusable="false"
|
|
402
|
+
[attr.inert]="idleInert"
|
|
403
|
+
role="presentation"
|
|
404
|
+
[style]="idleStyle"
|
|
405
|
+
viewBox="0 0 0 0"
|
|
406
|
+
>
|
|
407
|
+
<path
|
|
408
|
+
[attr.cursor]="idlePathCursor"
|
|
409
|
+
data-glow-tour-overlay-path
|
|
410
|
+
fill-rule="evenodd"
|
|
411
|
+
[attr.opacity]="idlePathOpacity"
|
|
412
|
+
[attr.pointer-events]="idlePathPointerEvents"
|
|
413
|
+
/><ng-content />
|
|
414
|
+
</svg>
|
|
415
|
+
`,
|
|
416
|
+
}]
|
|
417
|
+
}], propDecorators: { element: [{
|
|
418
|
+
type: ViewChild,
|
|
419
|
+
args: ["tourElement", { static: true }]
|
|
420
|
+
}] } });
|
|
421
|
+
class GlowTourTrigger extends GlowTourReactiveComponent {
|
|
422
|
+
ariaLabelValue = signal(undefined);
|
|
423
|
+
disabledValue = signal(false);
|
|
424
|
+
ariaLabelText = computed(() => this.ariaLabelValue());
|
|
425
|
+
consumerDisabled = computed(() => this.disabledValue());
|
|
426
|
+
ariaControls = computed(() => this.scope.binding()?.ids.popover);
|
|
427
|
+
setAriaLabel(value) {
|
|
428
|
+
this.ariaLabelValue.set(value);
|
|
429
|
+
}
|
|
430
|
+
setDisabled(value) {
|
|
431
|
+
this.disabledValue.set(value);
|
|
432
|
+
}
|
|
433
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourTrigger, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
434
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: GlowTourTrigger, usesInheritance: true, ngImport: i0 });
|
|
435
|
+
}
|
|
436
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourTrigger, decorators: [{
|
|
437
|
+
type: Directive
|
|
438
|
+
}] });
|
|
439
|
+
/** Button component for navigating to the previous step in the tour. */
|
|
440
|
+
export class GlowTourBackTrigger extends GlowTourTrigger {
|
|
441
|
+
backLabelValue = signal(undefined);
|
|
442
|
+
/** Optional aria-label for the back button. */
|
|
443
|
+
set ariaLabel(value) {
|
|
444
|
+
this.setAriaLabel(value);
|
|
445
|
+
}
|
|
446
|
+
/** Optional label text for the back button. */
|
|
447
|
+
set backLabel(value) {
|
|
448
|
+
this.backLabelValue.set(value);
|
|
449
|
+
}
|
|
450
|
+
/** Whether the button is disabled. */
|
|
451
|
+
set disabled(value) {
|
|
452
|
+
this.setDisabled(value);
|
|
453
|
+
}
|
|
454
|
+
isDisabled = computed(() => this.consumerDisabled() ||
|
|
455
|
+
!this.snapshot()?.canPrevious ||
|
|
456
|
+
this.step()?.popover?.disablePreviousButton === true);
|
|
457
|
+
label = computed(() => this.backLabelValue() ?? "Back step");
|
|
458
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourBackTrigger, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
459
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GlowTourBackTrigger, isStandalone: true, selector: "glow-tour-back-trigger", inputs: { ariaLabel: "ariaLabel", backLabel: "backLabel", disabled: ["disabled", "disabled", booleanAttribute] }, usesInheritance: true, ngImport: i0, template: `
|
|
460
|
+
@if (!step()?.popover?.hidePreviousButton) {
|
|
461
|
+
<button
|
|
462
|
+
data-glow-tour-previous-trigger
|
|
463
|
+
[attr.aria-controls]="ariaControls()"
|
|
464
|
+
[attr.aria-disabled]="isDisabled() ? 'true' : 'false'"
|
|
465
|
+
[attr.aria-label]="ariaLabelText() ?? label()"
|
|
466
|
+
[attr.data-glow-tour-consumer-disabled]="consumerDisabled() ? 'true' : null"
|
|
467
|
+
[disabled]="isDisabled()"
|
|
468
|
+
type="button"
|
|
469
|
+
><ng-content>{{ label() }}</ng-content></button>
|
|
470
|
+
}
|
|
471
|
+
`, isInline: true });
|
|
472
|
+
}
|
|
473
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourBackTrigger, decorators: [{
|
|
474
|
+
type: Component,
|
|
475
|
+
args: [{
|
|
476
|
+
selector: "glow-tour-back-trigger",
|
|
477
|
+
standalone: true,
|
|
478
|
+
template: `
|
|
479
|
+
@if (!step()?.popover?.hidePreviousButton) {
|
|
480
|
+
<button
|
|
481
|
+
data-glow-tour-previous-trigger
|
|
482
|
+
[attr.aria-controls]="ariaControls()"
|
|
483
|
+
[attr.aria-disabled]="isDisabled() ? 'true' : 'false'"
|
|
484
|
+
[attr.aria-label]="ariaLabelText() ?? label()"
|
|
485
|
+
[attr.data-glow-tour-consumer-disabled]="consumerDisabled() ? 'true' : null"
|
|
486
|
+
[disabled]="isDisabled()"
|
|
487
|
+
type="button"
|
|
488
|
+
><ng-content>{{ label() }}</ng-content></button>
|
|
489
|
+
}
|
|
490
|
+
`,
|
|
491
|
+
}]
|
|
492
|
+
}], propDecorators: { ariaLabel: [{
|
|
493
|
+
type: Input
|
|
494
|
+
}], backLabel: [{
|
|
495
|
+
type: Input
|
|
496
|
+
}], disabled: [{
|
|
497
|
+
type: Input,
|
|
498
|
+
args: [{ transform: booleanAttribute }]
|
|
499
|
+
}] } });
|
|
500
|
+
/** Button component for advancing to the next step or finishing the tour. */
|
|
501
|
+
export class GlowTourAdvanceTrigger extends GlowTourTrigger {
|
|
502
|
+
finishLabelValue = signal(undefined);
|
|
503
|
+
advanceLabelValue = signal(undefined);
|
|
504
|
+
/** Optional aria-label for the advance button. */
|
|
505
|
+
set ariaLabel(value) {
|
|
506
|
+
this.setAriaLabel(value);
|
|
507
|
+
}
|
|
508
|
+
/** Whether the button is disabled. */
|
|
509
|
+
set disabled(value) {
|
|
510
|
+
this.setDisabled(value);
|
|
511
|
+
}
|
|
512
|
+
/** Optional label text for the finish step. */
|
|
513
|
+
set finishLabel(value) {
|
|
514
|
+
this.finishLabelValue.set(value);
|
|
515
|
+
}
|
|
516
|
+
/** Optional label text for advancing to the next step. */
|
|
517
|
+
set advanceLabel(value) {
|
|
518
|
+
this.advanceLabelValue.set(value);
|
|
519
|
+
}
|
|
520
|
+
isDisabled = computed(() => this.consumerDisabled() ||
|
|
521
|
+
!this.snapshot()?.canAdvance ||
|
|
522
|
+
this.step()?.popover?.disableAdvanceButton === true);
|
|
523
|
+
label = computed(() => {
|
|
524
|
+
return this.snapshot()?.isLastStep
|
|
525
|
+
? (this.finishLabelValue() ?? "Finish tour")
|
|
526
|
+
: (this.advanceLabelValue() ?? "Advance step");
|
|
527
|
+
});
|
|
528
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourAdvanceTrigger, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
529
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GlowTourAdvanceTrigger, isStandalone: true, selector: "glow-tour-advance-trigger", inputs: { ariaLabel: "ariaLabel", disabled: ["disabled", "disabled", booleanAttribute], finishLabel: "finishLabel", advanceLabel: "advanceLabel" }, usesInheritance: true, ngImport: i0, template: `
|
|
530
|
+
@if (!step()?.popover?.hideAdvanceButton) {
|
|
531
|
+
<button
|
|
532
|
+
data-glow-tour-advance-trigger
|
|
533
|
+
[attr.aria-controls]="ariaControls()"
|
|
534
|
+
[attr.aria-disabled]="isDisabled() ? 'true' : 'false'"
|
|
535
|
+
[attr.aria-label]="ariaLabelText() ?? label()"
|
|
536
|
+
[attr.data-glow-tour-consumer-disabled]="consumerDisabled() ? 'true' : null"
|
|
537
|
+
[disabled]="isDisabled()"
|
|
538
|
+
type="button"
|
|
539
|
+
><ng-content>{{ label() }}</ng-content></button>
|
|
540
|
+
}
|
|
541
|
+
`, isInline: true });
|
|
542
|
+
}
|
|
543
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourAdvanceTrigger, decorators: [{
|
|
544
|
+
type: Component,
|
|
545
|
+
args: [{
|
|
546
|
+
selector: "glow-tour-advance-trigger",
|
|
547
|
+
standalone: true,
|
|
548
|
+
template: `
|
|
549
|
+
@if (!step()?.popover?.hideAdvanceButton) {
|
|
550
|
+
<button
|
|
551
|
+
data-glow-tour-advance-trigger
|
|
552
|
+
[attr.aria-controls]="ariaControls()"
|
|
553
|
+
[attr.aria-disabled]="isDisabled() ? 'true' : 'false'"
|
|
554
|
+
[attr.aria-label]="ariaLabelText() ?? label()"
|
|
555
|
+
[attr.data-glow-tour-consumer-disabled]="consumerDisabled() ? 'true' : null"
|
|
556
|
+
[disabled]="isDisabled()"
|
|
557
|
+
type="button"
|
|
558
|
+
><ng-content>{{ label() }}</ng-content></button>
|
|
559
|
+
}
|
|
560
|
+
`,
|
|
561
|
+
}]
|
|
562
|
+
}], propDecorators: { ariaLabel: [{
|
|
563
|
+
type: Input
|
|
564
|
+
}], disabled: [{
|
|
565
|
+
type: Input,
|
|
566
|
+
args: [{ transform: booleanAttribute }]
|
|
567
|
+
}], finishLabel: [{
|
|
568
|
+
type: Input
|
|
569
|
+
}], advanceLabel: [{
|
|
570
|
+
type: Input
|
|
571
|
+
}] } });
|
|
572
|
+
/** Button component for canceling/skipping the tour. */
|
|
573
|
+
export class GlowTourCancelTrigger extends GlowTourTrigger {
|
|
574
|
+
/** Optional aria-label for the cancel button. */
|
|
575
|
+
set ariaLabel(value) {
|
|
576
|
+
this.setAriaLabel(value);
|
|
577
|
+
}
|
|
578
|
+
/** Whether the button is disabled. */
|
|
579
|
+
set disabled(value) {
|
|
580
|
+
this.setDisabled(value);
|
|
581
|
+
}
|
|
582
|
+
isDisabled = computed(() => this.consumerDisabled() || !this.snapshot()?.canCancel);
|
|
583
|
+
label = computed(() => "Skip");
|
|
584
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourCancelTrigger, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
585
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GlowTourCancelTrigger, isStandalone: true, selector: "glow-tour-cancel-trigger", inputs: { ariaLabel: "ariaLabel", disabled: ["disabled", "disabled", booleanAttribute] }, usesInheritance: true, ngImport: i0, template: `
|
|
586
|
+
@if (snapshot()?.canCancel) {
|
|
587
|
+
<button
|
|
588
|
+
data-glow-tour-cancel-trigger
|
|
589
|
+
[attr.aria-controls]="ariaControls()"
|
|
590
|
+
[attr.aria-disabled]="isDisabled() ? 'true' : 'false'"
|
|
591
|
+
[attr.aria-label]="ariaLabelText() ?? label()"
|
|
592
|
+
[attr.data-glow-tour-consumer-disabled]="consumerDisabled() ? 'true' : null"
|
|
593
|
+
[disabled]="isDisabled()"
|
|
594
|
+
type="button"
|
|
595
|
+
><ng-content>{{ label() }}</ng-content></button>
|
|
596
|
+
}
|
|
597
|
+
`, isInline: true });
|
|
598
|
+
}
|
|
599
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GlowTourCancelTrigger, decorators: [{
|
|
600
|
+
type: Component,
|
|
601
|
+
args: [{
|
|
602
|
+
selector: "glow-tour-cancel-trigger",
|
|
603
|
+
standalone: true,
|
|
604
|
+
template: `
|
|
605
|
+
@if (snapshot()?.canCancel) {
|
|
606
|
+
<button
|
|
607
|
+
data-glow-tour-cancel-trigger
|
|
608
|
+
[attr.aria-controls]="ariaControls()"
|
|
609
|
+
[attr.aria-disabled]="isDisabled() ? 'true' : 'false'"
|
|
610
|
+
[attr.aria-label]="ariaLabelText() ?? label()"
|
|
611
|
+
[attr.data-glow-tour-consumer-disabled]="consumerDisabled() ? 'true' : null"
|
|
612
|
+
[disabled]="isDisabled()"
|
|
613
|
+
type="button"
|
|
614
|
+
><ng-content>{{ label() }}</ng-content></button>
|
|
615
|
+
}
|
|
616
|
+
`,
|
|
617
|
+
}]
|
|
618
|
+
}], propDecorators: { ariaLabel: [{
|
|
619
|
+
type: Input
|
|
620
|
+
}], disabled: [{
|
|
621
|
+
type: Input,
|
|
622
|
+
args: [{ transform: booleanAttribute }]
|
|
623
|
+
}] } });
|
|
624
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG91ci1jb21wb25lbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL3RvdXItY29tcG9uZW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNuRCxPQUFPLEVBQ0wsZ0JBQWdCLEVBQ2hCLFNBQVMsRUFDVCxRQUFRLEVBQ1IsVUFBVSxFQUNWLFNBQVMsRUFDVCxVQUFVLEVBQ1YsTUFBTSxFQUNOLFVBQVUsRUFDVixjQUFjLEVBQ2QsUUFBUSxFQUNSLEtBQUssRUFDTCxNQUFNLEVBS04sTUFBTSxFQUNOLFdBQVcsRUFDWCxTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUVMLG1CQUFtQixFQUNuQix1QkFBdUIsRUFDdkIsa0JBQWtCLEVBQ2xCLDRCQUE0QixFQUM1Qix1QkFBdUIsRUFDdkIsa0JBQWtCLEVBQ2xCLHVCQUF1QixFQUN2QixrQkFBa0IsRUFDbEIsb0JBQW9CLEdBQ3JCLE1BQU0sNEJBQTRCLENBQUM7O0FBR3BDLE1BQU0sdUJBQXVCLEdBQUcsb0JBQW9CLENBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUN6RSxNQUFNLHVCQUF1QixHQUFHLG9CQUFvQixDQUFDLGtCQUFrQixDQUFDLENBQUM7QUFDekUsTUFBTSx1QkFBdUIsR0FBRyxvQkFBb0IsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0FBZXpFLE1BQU0saUNBQWlDLEdBQXNDO0lBQzNFLE1BQU0sRUFBRSxJQUFJO0lBQ1osSUFBSSxFQUFFLElBQUk7SUFDVixLQUFLLEVBQUUsSUFBSTtJQUNYLEdBQUcsRUFBRSxJQUFJO0NBQ1YsQ0FBQztBQUVGLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQVUsQ0FBQztBQVN2RSxNQUNNLGFBQWE7SUFDUixPQUFPLEdBQUcsTUFB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QixLQUFLO2dCQUlzQyxRQUFRO3NCQUFuRCxLQUFLO3VCQUFDLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTmdUZW1wbGF0ZU91dGxldCB9IGZyb20gXCJAYW5ndWxhci9jb21tb25cIjtcbmltcG9ydCB7XG4gIGJvb2xlYW5BdHRyaWJ1dGUsXG4gIENvbXBvbmVudCxcbiAgY29tcHV0ZWQsXG4gIERlc3Ryb3lSZWYsXG4gIERpcmVjdGl2ZSxcbiAgRWxlbWVudFJlZixcbiAgZWZmZWN0LFxuICBJbmplY3RhYmxlLFxuICBJbmplY3Rpb25Ub2tlbixcbiAgSW5qZWN0b3IsXG4gIElucHV0LFxuICBpbmplY3QsXG4gIHR5cGUgT25DaGFuZ2VzLFxuICB0eXBlIE9uRGVzdHJveSxcbiAgdHlwZSBPbkluaXQsXG4gIHR5cGUgU2lnbmFsLFxuICBzaWduYWwsXG4gIFRlbXBsYXRlUmVmLFxuICBWaWV3Q2hpbGQsXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgdHlwZSB7IEdsb3dUb3VyIGFzIENvcmVHbG93VG91ciwgVG91clN0YXRlIH0gZnJvbSBcIkBnbG93aG9wL2NvcmUtdG91clwiO1xuaW1wb3J0IHtcbiAgdHlwZSBBZGFwdGVyUm9vdEJpbmRpbmcsXG4gIGNvbm5lY3RHbG93VG91clJvb3QsXG4gIE9WRVJMQVlfSURMRV9BVFRSSUJVVEVTLFxuICBPVkVSTEFZX0lETEVfU1RZTEUsXG4gIE9WRVJMQVlfUEFUSF9JRExFX0FUVFJJQlVURVMsXG4gIFBPSU5URVJfSURMRV9BVFRSSUJVVEVTLFxuICBQT0lOVEVSX0lETEVfU1RZTEUsXG4gIFBPUE9WRVJfSURMRV9BVFRSSUJVVEVTLFxuICBQT1BPVkVSX0lETEVfU1RZTEUsXG4gIHN0eWxlUmVjb3JkVG9Dc3NUZXh0LFxufSBmcm9tIFwiQGdsb3dob3AvY29yZS10b3VyL2FkYXB0ZXJcIjtcbmltcG9ydCB0eXBlIHsgQW5ndWxhclRvdXJDb250ZW50IH0gZnJvbSBcIi4uL2dsb3ctdG91clwiO1xuXG5jb25zdCBPVkVSTEFZX0lETEVfU1RZTEVfVEVYVCA9IHN0eWxlUmVjb3JkVG9Dc3NUZXh0KE9WRVJMQVlfSURMRV9TVFlMRSk7XG5jb25zdCBQT0lOVEVSX0lETEVfU1RZTEVfVEVYVCA9IHN0eWxlUmVjb3JkVG9Dc3NUZXh0KFBPSU5URVJfSURMRV9TVFlMRSk7XG5jb25zdCBQT1BPVkVSX0lETEVfU1RZTEVfVEVYVCA9IHN0eWxlUmVjb3JkVG9Dc3NUZXh0KFBPUE9WRVJfSURMRV9TVFlMRSk7XG5cbnR5cGUgVG91ciA9IENvcmVHbG93VG91cjxBbmd1bGFyVG91ckNvbnRlbnQ+O1xuXG4vKiogUG9pbnRlciBkaXJlY3Rpb24gY29udGVudCB2YWx1ZSB0eXBlOiBzdHJpbmcgb3IgVGVtcGxhdGVSZWYuICovXG5leHBvcnQgdHlwZSBQb2ludGVyRGlyZWN0aW9uVmFsdWUgPSBzdHJpbmcgfCBUZW1wbGF0ZVJlZjx1bmtub3duPjtcblxuLyoqIFBvaW50ZXIgZGlyZWN0aW9uIGNvbnRlbnQgY29uZmlndXJhdGlvbiBmb3IgY3VzdG9tIHBvaW50ZXIgY29udGVudC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUG9pbnRlckRpcmVjdGlvbkNvbnRlbnQge1xuICByZWFkb25seSB0b3A/OiBQb2ludGVyRGlyZWN0aW9uVmFsdWU7XG4gIHJlYWRvbmx5IGJvdHRvbT86IFBvaW50ZXJEaXJlY3Rpb25WYWx1ZTtcbiAgcmVhZG9ubHkgbGVmdD86IFBvaW50ZXJEaXJlY3Rpb25WYWx1ZTtcbiAgcmVhZG9ubHkgcmlnaHQ/OiBQb2ludGVyRGlyZWN0aW9uVmFsdWU7XG59XG5cbmNvbnN0IERFRkFVTFRfUE9JTlRFUl9ESVJFQ1RJT05fQ09OVEVOVDogUmVxdWlyZWQ8UG9pbnRlckRpcmVjdGlvbkNvbnRlbnQ+ID0ge1xuICBib3R0b206IFwi8J+Rh1wiLFxuICBsZWZ0OiBcIvCfkYhcIixcbiAgcmlnaHQ6IFwi8J+RiVwiLFxuICB0b3A6IFwi8J+RhlwiLFxufTtcblxuY29uc3QgUE9JTlRFUl9ESVJFQ1RJT05TID0gW1widG9wXCIsIFwiYm90dG9tXCIsIFwibGVmdFwiLCBcInJpZ2h0XCJdIGFzIGNvbnN0O1xuXG5pbnRlcmZhY2UgQWN0aXZlUm9vdEJpbmRpbmcge1xuICByZWFkb25seSBiaW5kaW5nOiBBZGFwdGVyUm9vdEJpbmRpbmc7XG4gIHJlYWRvbmx5IGlkUHJlZml4OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHJlYWRvbmx5IHJvb3Q6IEhUTUxFbGVtZW50O1xuICByZWFkb25seSB0b3VyOiBUb3VyO1xufVxuXG5ASW5qZWN0YWJsZSgpXG5jbGFzcyBHbG93VG91clNjb3BlIHtcbiAgcmVhZG9ubHkgYmluZGluZyA9IHNpZ25hbDxBZGFwdGVyUm9vdEJpbmRpbmcgfCBudWxsPihudWxsKTtcbiAgcmVhZG9ubHkgdG91ciA9IHNpZ25hbDxUb3VyIHwgbnVsbD4obnVsbCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgc25hcHNob3QgPSBzaWduYWw8VG91clN0YXRlPEFuZ3VsYXJUb3VyQ29udGVudD4gfCBudWxsPihudWxsKTtcbiAgcmVhZG9ubHkgc3RhdGUgPSB0aGlzLnNuYXBzaG90LmFzUmVhZG9ubHkoKTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBlZmZlY3QoXG4gICAgICAob25DbGVhbnVwKSA9PiB7XG4gICAgICAgIGNvbnN0IHRvdXIgPSB0aGlzLnRvdXIoKTtcbiAgICAgICAgaWYgKCF0b3VyKSB7XG4gICAgICAgICAgdGhpcy5zbmFwc2hvdC5zZXQobnVsbCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc25hcHNob3Quc2V0KHRvdXIuc3RhdGUuZ2V0KCkpO1xuICAgICAgICBvbkNsZWFudXAodG91ci5zdGF0ZS5zdWJzY3JpYmUoKHN0YXRlKSA9PiB0aGlzLnNuYXBzaG90LnNldChzdGF0ZSkpKTtcbiAgICAgIH0sXG4gICAgICB7IGFsbG93U2lnbmFsV3JpdGVzOiB0cnVlIH0sXG4gICAgKTtcbiAgfVxufVxuXG5jb25zdCBHTE9XX1RPVVJfU0NPUEUgPSBuZXcgSW5qZWN0aW9uVG9rZW48R2xvd1RvdXJTY29wZT4oXCJHbG93VG91clNjb3BlXCIpO1xuXG5mdW5jdGlvbiB1c2VUb3VyU2NvcGUoKSB7XG4gIGNvbnN0IHNjb3BlID0gaW5qZWN0KEdMT1dfVE9VUl9TQ09QRSwgeyBvcHRpb25hbDogdHJ1ZSB9KTtcbiAgaWYgKCFzY29wZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignR2xvd1RvdXIgY29tcG9uZW50cyBtdXN0IGJlIHJlbmRlcmVkIGluc2lkZSA8Z2xvdy10b3VyLXJvb3QgW3RvdXJdPVwiLi4uXCI+LicpO1xuICB9XG4gIHJldHVybiBzY29wZTtcbn1cblxuLyoqXG4gKiBJbmplY3RzIHRoZSB0b3VyIHN0YXRlIHNpZ25hbCBpbnRvIGEgY29tcG9uZW50LlxuICogTXVzdCBiZSBjYWxsZWQgd2l0aGluIGEgR2xvd1RvdXJSb290IGNvbXBvbmVudCBjb250ZXh0LlxuICogQHJldHVybnMgQSBzaWduYWwgY29udGFpbmluZyB0aGUgY3VycmVudCB0b3VyIHN0YXRlIG9yIG51bGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmplY3RHbG93VG91cigpOiBTaWduYWw8VG91clN0YXRlPEFuZ3VsYXJUb3VyQ29udGVudD4gfCBudWxsPiB7XG4gIHJldHVybiB1c2VUb3VyU2NvcGUoKS5zdGF0ZTtcbn1cblxuQERpcmVjdGl2ZSgpXG5hYnN0cmFjdCBjbGFzcyBHbG93VG91clJlYWN0aXZlQ29tcG9uZW50IHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHNjb3BlID0gdXNlVG91clNjb3BlKCk7XG4gIHByb3RlY3RlZCByZWFkb25seSBzbmFwc2hvdCA9IHRoaXMuc2NvcGUuc3RhdGU7XG4gIHByb3RlY3RlZCByZWFkb25seSBzdGVwID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5zbmFwc2hvdCgpPy5jdXJyZW50U3RlcD8uY3VycmVudFByb3BzID8/IG51bGwpO1xufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6IFwiZ2xvdy10b3VyLXJvb3RcIixcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaG9zdDogeyBcImRhdGEtZ2xvdy10b3VyLXJvb3RcIjogXCJcIiB9LFxuICBwcm92aWRlcnM6IFtHbG93VG91clNjb3BlLCB7IHByb3ZpZGU6IEdMT1dfVE9VUl9TQ09QRSwgdXNlRXhpc3Rpbmc6IEdsb3dUb3VyU2NvcGUgfV0sXG4gIHRlbXBsYXRlOiBcIjxuZy1jb250ZW50IC8+XCIsXG59KVxuLyoqIFJvb3QgY29udGFpbmVyIGNvbXBvbmVudCBmb3IgR2xvd1RvdXIuanMuIFByb3ZpZGVzIHRvdXIgY29udGV4dCBhbmQgbWFuYWdlcyB0aGUgcm9vdCBiaW5kaW5nLiAqL1xuZXhwb3J0IGNsYXNzIEdsb3dUb3VyUm9vdCBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgT25EZXN0cm95LCBPbkluaXQge1xuICAvKiogVGhlIHRvdXIgY29udHJvbGxlciBpbnN0YW5jZSB0byBkaXNwbGF5LiAqL1xuICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KSB0b3VyITogVG91cjtcbiAgLyoqIE9wdGlvbmFsIHByZWZpeCBmb3IgZ2VuZXJhdGVkIEhUTUwgSURzLiAqL1xuICBASW5wdXQoKSBpZFByZWZpeD86IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IGVsZW1lbnQgPSBpbmplY3QoRWxlbWVudFJlZjxIVE1MRWxlbWVudD4pO1xuICBwcml2YXRlIHJlYWRvbmx5IHNjb3BlID0gaW5qZWN0KEdsb3dUb3VyU2NvcGUpO1xuICBwcml2YXRlIGFjdGl2ZTogQWN0aXZlUm9vdEJpbmRpbmcgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBpbml0aWFsaXplZCA9IGZhbHNlO1xuXG4gIG5nT25DaGFuZ2VzKCkge1xuICAgIGlmICh0aGlzLmluaXRpYWxpemVkKSB0aGlzLnJlY29uY2lsZSgpO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgaWYgKCF0aGlzLnRvdXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkdsb3dUb3VyUm9vdCByZXF1aXJlcyBhIHRvdXIgaW5wdXQuXCIpO1xuICAgIH1cblxuICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIHRoaXMucmVjb25jaWxlKCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLnJlbGVhc2UoKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVjb25jaWxlKCkge1xuICAgIGNvbnN0IHJvb3QgPSB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudDtcbiAgICBjb25zdCB0b3VyID0gdGhpcy50b3VyO1xuICAgIGNvbnN0IGlkUHJlZml4ID0gdGhpcy5pZFByZWZpeDtcbiAgICB0aGlzLnNjb3BlLnRvdXIuc2V0KHRvdXIpO1xuICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLmFjdGl2ZTtcbiAgICBpZiAoXG4gICAgICBjdXJyZW50ICE9PSBudWxsICYmXG4gICAgICBjdXJyZW50LnJvb3QgPT09IHJvb3QgJiZcbiAgICAgIGN1cnJlbnQudG91ciA9PT0gdG91ciAmJlxuICAgICAgY3VycmVudC5pZFByZWZpeCA9PT0gaWRQcmVmaXhcbiAgICApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5yZWxlYXNlKCk7XG4gICAgY29uc3QgYmluZGluZyA9IGNvbm5lY3RHbG93VG91clJvb3QodG91ciwge1xuICAgICAgaWRQcmVmaXgsXG4gICAgICByb290LFxuICAgIH0pO1xuICAgIGNvbnN0IGFjdGl2ZSA9IHsgYmluZGluZywgaWRQcmVmaXgsIHJvb3QsIHRvdXIgfTtcbiAgICB0aGlzLmFjdGl2ZSA9IGFjdGl2ZTtcbiAgICB0aGlzLnNjb3BlLmJpbmRpbmcuc2V0KGJpbmRpbmcpO1xuICB9XG5cbiAgcHJpdmF0ZSByZWxlYXNlKCkge1xuICAgIGNvbnN0IGFjdGl2ZSA9IHRoaXMuYWN0aXZlO1xuICAgIGlmICghYWN0aXZlKSByZXR1cm47XG4gICAgdGhpcy5hY3RpdmUgPSBudWxsO1xuICAgIGFjdGl2ZS5iaW5kaW5nLnJlbGVhc2UoKTtcbiAgICBpZiAodGhpcy5zY29wZS5iaW5kaW5nKCkgPT09IGFjdGl2ZS5iaW5kaW5nKSB0aGlzLnNjb3BlLmJpbmRpbmcuc2V0KG51bGwpO1xuICB9XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJnbG93LXRvdXItaGVhZGVyXCIsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtOZ1RlbXBsYXRlT3V0bGV0XSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8aGVhZGVyIGRhdGEtZ2xvdy10b3VyLWhlYWRlciBbaWRdPVwic2NvcGUuYmluZGluZygpPy5pZHM/LnRpdGxlXCI+XG4gICAgICBAaWYgKHRpdGxlVGVtcGxhdGUoKSkge1xuICAgICAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cInRpdGxlVGVtcGxhdGUoKVwiIC8+XG4gICAgICB9IEBlbHNlIHtcbiAgICAgICAge3sgdGl0bGVUZXh0KCkgfX1cbiAgICAgIH1cbiAgICA8L2hlYWRlcj5cbiAgYCxcbn0pXG4vKiogSGVhZGVyIGNvbXBvbmVudCBkaXNwbGF5aW5nIHRoZSBjdXJyZW50IHN0ZXAncyB0aXRsZS4gKi9cbmV4cG9ydCBjbGFzcyBHbG93VG91ckhlYWRlciBleHRlbmRzIEdsb3dUb3VyUmVhY3RpdmVDb21wb25lbnQge1xuICByZWFkb25seSB0aXRsZVRlbXBsYXRlID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IHRpdGxlID0gdGhpcy5zdGVwKCk/LnRpdGxlO1xuICAgIHJldHVybiB0aXRsZSBpbnN0YW5jZW9mIFRlbXBsYXRlUmVmID8gdGl0bGUgOiBudWxsO1xuICB9KTtcbiAgcmVhZG9ubHkgdGl0bGVUZXh0ID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IHRpdGxlID0gdGhpcy5zdGVwKCk/LnRpdGxlO1xuICAgIHJldHVybiB0eXBlb2YgdGl0bGUgPT09IFwic3RyaW5nXCIgPyB0aXRsZSA6IFwiXCI7XG4gIH0pO1xufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6IFwiZ2xvdy10b3VyLWNvbnRlbnRcIixcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW05nVGVtcGxhdGVPdXRsZXRdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgYXJpYS1saXZlPVwicG9saXRlXCIgZGF0YS1nbG93LXRvdXItY29udGVudCBbaWRdPVwic2NvcGUuYmluZGluZygpPy5pZHM/LmRlc2NyaXB0aW9uXCI+XG4gICAgICBAaWYgKGNvbnRlbnRUZW1wbGF0ZSgpKSB7XG4gICAgICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwiY29udGVudFRlbXBsYXRlKClcIiAvPlxuICAgICAgfSBAZWxzZSB7XG4gICAgICAgIHt7IGNvbnRlbnRUZXh0KCkgfX1cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgYCxcbn0pXG4vKiogQ29udGVudCBjb21wb25lbnQgZGlzcGxheWluZyB0aGUgY3VycmVudCBzdGVwJ3MgY29udGVudCB3aXRoIGxpdmUgcmVnaW9uLiAqL1xuZXhwb3J0IGNsYXNzIEdsb3dUb3VyQ29udGVudCBleHRlbmRzIEdsb3dUb3VyUmVhY3RpdmVDb21wb25lbnQge1xuICByZWFkb25seSBjb250ZW50VGVtcGxhdGUgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgY29udGVudCA9IHRoaXMuc3RlcCgpPy5jb250ZW50O1xuICAgIHJldHVybiBjb250ZW50IGluc3RhbmNlb2YgVGVtcGxhdGVSZWYgPyBjb250ZW50IDogbnVsbDtcbiAgfSk7XG4gIHJlYWRvbmx5IGNvbnRlbnRUZXh0ID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IGNvbnRlbnQgPSB0aGlzLnN0ZXAoKT8uY29udGVudDtcbiAgICByZXR1cm4gdHlwZW9mIGNvbnRlbnQgPT09IFwic3RyaW5nXCIgPyBjb250ZW50IDogXCJcIjtcbiAgfSk7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJnbG93LXRvdXItZm9vdGVyXCIsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHRlbXBsYXRlOiBgQGlmICghc3RlcCgpPy5wb3BvdmVyPy5oaWRlRm9vdGVyKSB7IDxmb290ZXIgZGF0YS1nbG93LXRvdXItZm9vdGVyPjxuZy1jb250ZW50IC8+PC9mb290ZXI+IH1gLFxufSlcbi8qKiBGb290ZXIgY29tcG9uZW50IGNvbnRhaW5pbmcgYWN0aW9uIGJ1dHRvbnMuIENvbmRpdGlvbmFsbHkgcmVuZGVyZWQgYmFzZWQgb24gdG91ciBzdGVwIGNvbmZpZ3VyYXRpb24uICovXG5leHBvcnQgY2xhc3MgR2xvd1RvdXJGb290ZXIgZXh0ZW5kcyBHbG93VG91clJlYWN0aXZlQ29tcG9uZW50IHt9XG5cbkBEaXJlY3RpdmUoKVxuYWJzdHJhY3QgY2xhc3MgR2xvd1RvdXJCb3VuZEVsZW1lbnQ8VCBleHRlbmRzIEVsZW1lbnQ+IHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHNjb3BlID0gdXNlVG91clNjb3BlKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVzdHJveVJlZiA9IGluamVjdChEZXN0cm95UmVmKTtcbiAgcHJpdmF0ZSByZWFkb25seSBpbmplY3RvciA9IGluamVjdChJbmplY3Rvcik7XG5cbiAgcHJvdGVjdGVkIGJpbmQoZWxlbWVudDogVCwgYmluZEVsZW1lbnQ6IChiaW5kaW5nOiBBZGFwdGVyUm9vdEJpbmRpbmcsIGVsZW1lbnQ6IFQpID0+ICgpID0+IHZvaWQpIHtcbiAgICBjb25zdCBjbGVhbnVwID0gZWZmZWN0KFxuICAgICAgKG9uQ2xlYW51cCkgPT4ge1xuICAgICAgICBjb25zdCBiaW5kaW5nID0gdGhpcy5zY29wZS5iaW5kaW5nKCk7XG4gICAgICAgIGlmIChiaW5kaW5nKSBvbkNsZWFudXAoYmluZEVsZW1lbnQoYmluZGluZywgZWxlbWVudCkpO1xuICAgICAgfSxcbiAgICAgIHsgaW5qZWN0b3I6IHRoaXMuaW5qZWN0b3IgfSxcbiAgICApO1xuICAgIHRoaXMuZGVzdHJveVJlZi5vbkRlc3Ryb3koKCkgPT4gY2xlYW51cC5kZXN0cm95KCkpO1xuICB9XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJnbG93LXRvdXItcG9wb3ZlclwiLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICAvLyBUaGUgaWRsZSBhdHRyaWJ1dGVzL3N0eWxlIGNvbWUgZnJvbSBpbXBvcnRlZCBgQGdsb3dob3AvY29yZS10b3VyL2FkYXB0ZXJgXG4gIC8vIGNvbnN0YW50cywgc28gbmdjJ3MgQU9UIHRlbXBsYXRlIGFuYWx5emVyIChORzEwMTApIGNhbm5vdCBpbmxpbmUgdGhlbSBhc1xuICAvLyBzdHJpbmctaW50ZXJwb2xhdGVkIGxpdGVyYWxzIGluIHRoZSB0ZW1wbGF0ZS4gQm91bmQgdmlhIGNvbXBvbmVudCBmaWVsZHNcbiAgLy8gaW5zdGVhZDsgdGhlIHZhbHVlcyBhcmUgc3RpbGwgc3RhdGljLCBzbyBzZXJ2ZXIgYW5kIGNsaWVudCByZW5kZXJcbiAgLy8gYnl0ZS1pZGVudGljYWwgb3V0cHV0LlxuICB0ZW1wbGF0ZTogYFxuICAgIDxzZWN0aW9uICN0b3VyRWxlbWVudFxuICAgICAgW2F0dHIuYXJpYS1oaWRkZW5dPVwiaWRsZUFyaWFIaWRkZW5cIlxuICAgICAgZGF0YS1nbG93LXRvdXItcG9wb3ZlclxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJzY29wZS5iaW5kaW5nKCk/Lmlkcz8uZGVzY3JpcHRpb25cIlxuICAgICAgW2F0dHIuYXJpYS1sYWJlbGxlZGJ5XT1cInNjb3BlLmJpbmRpbmcoKT8uaWRzPy50aXRsZVwiXG4gICAgICBbaWRdPVwic2NvcGUuYmluZGluZygpPy5pZHM/LnBvcG92ZXJcIlxuICAgICAgW2F0dHIuaW5lcnRdPVwiaWRsZUluZXJ0XCJcbiAgICAgIHJvbGU9XCJkaWFsb2dcIlxuICAgICAgW3N0eWxlXT1cImlkbGVTdHlsZVwiXG4gICAgICB0YWJpbmRleD1cIi0xXCJcbiAgICA+PG5nLWNvbnRlbnQgLz48L3NlY3Rpb24+XG4gIGAsXG59KVxuLyoqIFBvcG92ZXIgY29tcG9uZW50IGNvbnRhaW5pbmcgdGhlIHRvdXIgY29udGVudCB3aXRoIGFjY2Vzc2liaWxpdHkgYXR0cmlidXRlcy4gKi9cbmV4cG9ydCBjbGFzcyBHbG93VG91clBvcG92ZXIgZXh0ZW5kcyBHbG93VG91ckJvdW5kRWxlbWVudDxIVE1MRWxlbWVudD4gaW1wbGVtZW50cyBPbkluaXQge1xuICBAVmlld0NoaWxkKFwidG91ckVsZW1lbnRcIiwgeyBzdGF0aWM6IHRydWUgfSkgcHJpdmF0ZSByZWFkb25seSBlbGVtZW50ITogRWxlbWVudFJlZjxIVE1MRWxlbWVudD47XG4gIHByb3RlY3RlZCByZWFkb25seSBpZGxlQXJpYUhpZGRlbiA9IFBPUE9WRVJfSURMRV9BVFRSSUJVVEVTW1wiYXJpYS1oaWRkZW5cIl07XG4gIHByb3RlY3RlZCByZWFkb25seSBpZGxlSW5lcnQgPSBQT1BPVkVSX0lETEVfQVRUUklCVVRFUy5pbmVydDtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkbGVTdHlsZSA9IFBPUE9WRVJfSURMRV9TVFlMRV9URVhUO1xuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuYmluZCh0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudCwgKGJpbmRpbmcsIGVsZW1lbnQpID0+IGJpbmRpbmcuYmluZFBvcG92ZXIoZWxlbWVudCkpO1xuICB9XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJnbG93LXRvdXItcG9pbnRlclwiLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbTmdUZW1wbGF0ZU91dGxldF0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiAjdG91ckVsZW1lbnQgZGF0YS1nbG93LXRvdXItcG9pbnRlciBbYXR0ci5hcmlhLWhpZGRlbl09XCJpZGxlQXJpYUhpZGRlblwiIFtzdHlsZV09XCJpZGxlU3R5bGVcIj5cbiAgICAgIEBmb3IgKGRpcmVjdGlvbiBvZiBkaXJlY3Rpb25zOyB0cmFjayBkaXJlY3Rpb24pIHtcbiAgICAgICAgPGRpdiBbYXR0ci5kYXRhLWdsb3ctdG91ci1wb2ludGVyLWRpcmVjdGlvbl09XCJkaXJlY3Rpb25cIj5cbiAgICAgICAgICBAaWYgKGFzVGVtcGxhdGUoY29udGVudCgpW2RpcmVjdGlvbl0pOyBhcyB0ZW1wbGF0ZSkge1xuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJ0ZW1wbGF0ZVwiIC8+XG4gICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICB7eyBjb250ZW50KClbZGlyZWN0aW9uXSB9fVxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuLyoqIFBvaW50ZXIgY29tcG9uZW50IGRpc3BsYXlpbmcgZGlyZWN0aW9uYWwgaW5kaWNhdG9ycyBwb2ludGluZyB0byB0aGUgdGFyZ2V0IGVsZW1lbnQuICovXG5leHBvcnQgY2xhc3MgR2xvd1RvdXJQb2ludGVyIGV4dGVuZHMgR2xvd1RvdXJCb3VuZEVsZW1lbnQ8SFRNTEVsZW1lbnQ+IGltcGxlbWVudHMgT25Jbml0IHtcbiAgQFZpZXdDaGlsZChcInRvdXJFbGVtZW50XCIsIHsgc3RhdGljOiB0cnVlIH0pIHByaXZhdGUgcmVhZG9ubHkgZWxlbWVudCE6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+O1xuICBwcml2YXRlIHJlYWRvbmx5IGRpcmVjdGlvbkNvbnRlbnRWYWx1ZSA9IHNpZ25hbDxQb2ludGVyRGlyZWN0aW9uQ29udGVudCB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkbGVBcmlhSGlkZGVuID0gUE9JTlRFUl9JRExFX0FUVFJJQlVURVNbXCJhcmlhLWhpZGRlblwiXTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkbGVTdHlsZSA9IFBPSU5URVJfSURMRV9TVFlMRV9URVhUO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBkaXJlY3Rpb25zID0gUE9JTlRFUl9ESVJFQ1RJT05TO1xuICByZWFkb25seSBjb250ZW50ID0gY29tcHV0ZWQoKCkgPT4gKHtcbiAgICAuLi5ERUZBVUxUX1BPSU5URVJfRElSRUNUSU9OX0NPTlRFTlQsXG4gICAgLi4udGhpcy5kaXJlY3Rpb25Db250ZW50VmFsdWUoKSxcbiAgfSkpO1xuXG4gIC8qKiBPcHRpb25hbCBjdXN0b20gY29udGVudCBmb3IgZWFjaCBwb2ludGVyIGRpcmVjdGlvbi4gKi9cbiAgQElucHV0KCkgc2V0IGRpcmVjdGlvbkNvbnRlbnQodmFsdWU6IFBvaW50ZXJEaXJlY3Rpb25Db250ZW50IHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5kaXJlY3Rpb25Db250ZW50VmFsdWUuc2V0KHZhbHVlKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc1RlbXBsYXRlKHZhbHVlOiBQb2ludGVyRGlyZWN0aW9uVmFsdWUpOiBUZW1wbGF0ZVJlZjx1bmtub3duPiB8IG51bGwge1xuICAgIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFRlbXBsYXRlUmVmID8gdmFsdWUgOiBudWxsO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5iaW5kKHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LCAoYmluZGluZywgZWxlbWVudCkgPT4gYmluZGluZy5iaW5kUG9pbnRlcihlbGVtZW50KSk7XG4gIH1cbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcImdsb3ctdG91ci1vdmVybGF5XCIsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHRlbXBsYXRlOiBgXG4gICAgPHN2ZyAjdG91ckVsZW1lbnRcbiAgICAgIFthdHRyLmFyaWEtaGlkZGVuXT1cImlkbGVBcmlhSGlkZGVuXCJcbiAgICAgIFthdHRyLmRhdGEtZ2xvdy10b3VyLWFsbG93LWludGVyYWN0aW9uXT1cImlkbGVBbGxvd0ludGVyYWN0aW9uXCJcbiAgICAgIGRhdGEtZ2xvdy10b3VyLW92ZXJsYXlcbiAgICAgIGZvY3VzYWJsZT1cImZhbHNlXCJcbiAgICAgIFthdHRyLmluZXJ0XT1cImlkbGVJbmVydFwiXG4gICAgICByb2xlPVwicHJlc2VudGF0aW9uXCJcbiAgICAgIFtzdHlsZV09XCJpZGxlU3R5bGVcIlxuICAgICAgdmlld0JveD1cIjAgMCAwIDBcIlxuICAgID5cbiAgICAgIDxwYXRoXG4gICAgICAgIFthdHRyLmN1cnNvcl09XCJpZGxlUGF0aEN1cnNvclwiXG4gICAgICAgIGRhdGEtZ2xvdy10b3VyLW92ZXJsYXktcGF0aFxuICAgICAgICBmaWxsLXJ1bGU9XCJldmVub2RkXCJcbiAgICAgICAgW2F0dHIub3BhY2l0eV09XCJpZGxlUGF0aE9wYWNpdHlcIlxuICAgICAgICBbYXR0ci5wb2ludGVyLWV2ZW50c109XCJpZGxlUGF0aFBvaW50ZXJFdmVudHNcIlxuICAgICAgLz48bmctY29udGVudCAvPlxuICAgIDwvc3ZnPlxuICBgLFxufSlcbi8qKiBPdmVybGF5IGNvbXBvbmVudCByZW5kZXJpbmcgYSBjbGlwcGVkIFNWRyBtYXNrIGhpZ2hsaWdodGluZyB0aGUgdGFyZ2V0IGVsZW1lbnQuICovXG5leHBvcnQgY2xhc3MgR2xvd1RvdXJPdmVybGF5IGV4dGVuZHMgR2xvd1RvdXJCb3VuZEVsZW1lbnQ8U1ZHU1ZHRWxlbWVudD4gaW1wbGVtZW50cyBPbkluaXQge1xuICBAVmlld0NoaWxkKFwidG91ckVsZW1lbnRcIiwgeyBzdGF0aWM6IHRydWUgfSkgcHJpdmF0ZSByZWFkb25seSBlbGVtZW50ITogRWxlbWVudFJlZjxTVkdTVkdFbGVtZW50PjtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkbGVBcmlhSGlkZGVuID0gT1ZFUkxBWV9JRExFX0FUVFJJQlVURVNbXCJhcmlhLWhpZGRlblwiXTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkbGVBbGxvd0ludGVyYWN0aW9uID1cbiAgICBPVkVSTEFZX0lETEVfQVRUUklCVVRFU1tcImRhdGEtZ2xvdy10b3VyLWFsbG93LWludGVyYWN0aW9uXCJdO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgaWRsZUluZXJ0ID0gT1ZFUkxBWV9JRExFX0FUVFJJQlVURVMuaW5lcnQ7XG4gIHByb3RlY3RlZCByZWFkb25seSBpZGxlU3R5bGUgPSBPVkVSTEFZX0lETEVfU1RZTEVfVEVYVDtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkbGVQYXRoQ3Vyc29yID0gT1ZFUkxBWV9QQVRIX0lETEVfQVRUUklCVVRFUy5jdXJzb3I7XG4gIHByb3RlY3RlZCByZWFkb25seSBpZGxlUGF0aE9wYWNpdHkgPSBPVkVSTEFZX1BBVEhfSURMRV9BVFRSSUJVVEVTLm9wYWNpdHk7XG4gIHByb3RlY3RlZCByZWFkb25seSBpZGxlUGF0aFBvaW50ZXJFdmVudHMgPSBPVkVSTEFZX1BBVEhfSURMRV9BVFRSSUJVVEVTW1wicG9pbnRlci1ldmVudHNcIl07XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5iaW5kKHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LCAoYmluZGluZywgZWxlbWVudCkgPT4gYmluZGluZy5iaW5kT3ZlcmxheShlbGVtZW50KSk7XG4gIH1cbn1cblxuQERpcmVjdGl2ZSgpXG5hYnN0cmFjdCBjbGFzcyBHbG93VG91clRyaWdnZXIgZXh0ZW5kcyBHbG93VG91clJlYWN0aXZlQ29tcG9uZW50IHtcbiAgcHJpdmF0ZSByZWFkb25seSBhcmlhTGFiZWxWYWx1ZSA9IHNpZ25hbDxzdHJpbmcgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGlzYWJsZWRWYWx1ZSA9IHNpZ25hbChmYWxzZSk7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGFyaWFMYWJlbFRleHQgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmFyaWFMYWJlbFZhbHVlKCkpO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgY29uc3VtZXJEaXNhYmxlZCA9IGNvbXB1dGVkKCgpID0+IHRoaXMuZGlzYWJsZWRWYWx1ZSgpKTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGFyaWFDb250cm9scyA9IGNvbXB1dGVkKCgpID0+IHRoaXMuc2NvcGUuYmluZGluZygpPy5pZHMucG9wb3Zlcik7XG5cbiAgcHJvdGVjdGVkIHNldEFyaWFMYWJlbCh2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5hcmlhTGFiZWxWYWx1ZS5zZXQodmFsdWUpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHNldERpc2FibGVkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5kaXNhYmxlZFZhbHVlLnNldCh2YWx1ZSk7XG4gIH1cbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcImdsb3ctdG91ci1iYWNrLXRyaWdnZXJcIixcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgdGVtcGxhdGU6IGBcbiAgICBAaWYgKCFzdGVwKCk/LnBvcG92ZXI/LmhpZGVQcmV2aW91c0J1dHRvbikge1xuICAgICAgPGJ1dHRvblxuICAgICAgICBkYXRhLWdsb3ctdG91ci1wcmV2aW91cy10cmlnZ2VyXG4gICAgICAgIFthdHRyLmFyaWEtY29udHJvbHNdPVwiYXJpYUNvbnRyb2xzKClcIlxuICAgICAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cImlzRGlzYWJsZWQoKSA/ICd0cnVlJyA6ICdmYWxzZSdcIlxuICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbFRleHQoKSA/PyBsYWJlbCgpXCJcbiAgICAgICAgW2F0dHIuZGF0YS1nbG93LXRvdXItY29uc3VtZXItZGlzYWJsZWRdPVwiY29uc3VtZXJEaXNhYmxlZCgpID8gJ3RydWUnIDogbnVsbFwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkKClcIlxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgID48bmctY29udGVudD57eyBsYWJlbCgpIH19PC9uZy1jb250ZW50PjwvYnV0dG9uPlxuICAgIH1cbiAgYCxcbn0pXG4vKiogQnV0dG9uIGNvbXBvbmVudCBmb3IgbmF2aWdhdGluZyB0byB0aGUgcHJldmlvdXMgc3RlcCBpbiB0aGUgdG91ci4gKi9cbmV4cG9ydCBjbGFzcyBHbG93VG91ckJhY2tUcmlnZ2VyIGV4dGVuZHMgR2xvd1RvdXJUcmlnZ2VyIHtcbiAgcHJpdmF0ZSByZWFkb25seSBiYWNrTGFiZWxWYWx1ZSA9IHNpZ25hbDxzdHJpbmcgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG5cbiAgLyoqIE9wdGlvbmFsIGFyaWEtbGFiZWwgZm9yIHRoZSBiYWNrIGJ1dHRvbi4gKi9cbiAgQElucHV0KCkgc2V0IGFyaWFMYWJlbCh2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5zZXRBcmlhTGFiZWwodmFsdWUpO1xuICB9XG4gIC8qKiBPcHRpb25hbCBsYWJlbCB0ZXh0IGZvciB0aGUgYmFjayBidXR0b24uICovXG4gIEBJbnB1dCgpIHNldCBiYWNrTGFiZWwodmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCkge1xuICAgIHRoaXMuYmFja0xhYmVsVmFsdWUuc2V0KHZhbHVlKTtcbiAgfVxuICAvKiogV2hldGhlciB0aGUgYnV0dG9uIGlzIGRpc2FibGVkLiAqL1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgc2V0IGRpc2FibGVkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5zZXREaXNhYmxlZCh2YWx1ZSk7XG4gIH1cblxuICByZWFkb25seSBpc0Rpc2FibGVkID0gY29tcHV0ZWQoXG4gICAgKCkgPT5cbiAgICAgIHRoaXMuY29uc3VtZXJEaXNhYmxlZCgpIHx8XG4gICAgICAhdGhpcy5zbmFwc2hvdCgpPy5jYW5QcmV2aW91cyB8fFxuICAgICAgdGhpcy5zdGVwKCk/LnBvcG92ZXI/LmRpc2FibGVQcmV2aW91c0J1dHRvbiA9PT0gdHJ1ZSxcbiAgKTtcbiAgcmVhZG9ubHkgbGFiZWwgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmJhY2tMYWJlbFZhbHVlKCkgPz8gXCJCYWNrIHN0ZXBcIik7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJnbG93LXRvdXItYWR2YW5jZS10cmlnZ2VyXCIsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHRlbXBsYXRlOiBgXG4gICAgQGlmICghc3RlcCgpPy5wb3BvdmVyPy5oaWRlQWR2YW5jZUJ1dHRvbikge1xuICAgICAgPGJ1dHRvblxuICAgICAgICBkYXRhLWdsb3ctdG91ci1hZHZhbmNlLXRyaWdnZXJcbiAgICAgICAgW2F0dHIuYXJpYS1jb250cm9sc109XCJhcmlhQ29udHJvbHMoKVwiXG4gICAgICAgIFthdHRyLmFyaWEtZGlzYWJsZWRdPVwiaXNEaXNhYmxlZCgpID8gJ3RydWUnIDogJ2ZhbHNlJ1wiXG4gICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiYXJpYUxhYmVsVGV4dCgpID8/IGxhYmVsKClcIlxuICAgICAgICBbYXR0ci5kYXRhLWdsb3ctdG91ci1jb25zdW1lci1kaXNhYmxlZF09XCJjb25zdW1lckRpc2FibGVkKCkgPyAndHJ1ZScgOiBudWxsXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cImlzRGlzYWJsZWQoKVwiXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgPjxuZy1jb250ZW50Pnt7IGxhYmVsKCkgfX08L25nLWNvbnRlbnQ+PC9idXR0b24+XG4gICAgfVxuICBgLFxufSlcbi8qKiBCdXR0b24gY29tcG9uZW50IGZvciBhZHZhbmNpbmcgdG8gdGhlIG5leHQgc3RlcCBvciBmaW5pc2hpbmcgdGhlIHRvdXIuICovXG5leHBvcnQgY2xhc3MgR2xvd1RvdXJBZHZhbmNlVHJpZ2dlciBleHRlbmRzIEdsb3dUb3VyVHJpZ2dlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgZmluaXNoTGFiZWxWYWx1ZSA9IHNpZ25hbDxzdHJpbmcgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgYWR2YW5jZUxhYmVsVmFsdWUgPSBzaWduYWw8c3RyaW5nIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuXG4gIC8qKiBPcHRpb25hbCBhcmlhLWxhYmVsIGZvciB0aGUgYWR2YW5jZSBidXR0b24uICovXG4gIEBJbnB1dCgpIHNldCBhcmlhTGFiZWwodmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCkge1xuICAgIHRoaXMuc2V0QXJpYUxhYmVsKHZhbHVlKTtcbiAgfVxuICAvKiogV2hldGhlciB0aGUgYnV0dG9uIGlzIGRpc2FibGVkLiAqL1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGJvb2xlYW5BdHRyaWJ1dGUgfSkgc2V0IGRpc2FibGVkKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5zZXREaXNhYmxlZCh2YWx1ZSk7XG4gIH1cbiAgLyoqIE9wdGlvbmFsIGxhYmVsIHRleHQgZm9yIHRoZSBmaW5pc2ggc3RlcC4gKi9cbiAgQElucHV0KCkgc2V0IGZpbmlzaExhYmVsKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLmZpbmlzaExhYmVsVmFsdWUuc2V0KHZhbHVlKTtcbiAgfVxuICAvKiogT3B0aW9uYWwgbGFiZWwgdGV4dCBmb3IgYWR2YW5jaW5nIHRvIHRoZSBuZXh0IHN0ZXAuICovXG4gIEBJbnB1dCgpIHNldCBhZHZhbmNlTGFiZWwodmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCkge1xuICAgIHRoaXMuYWR2YW5jZUxhYmVsVmFsdWUuc2V0KHZhbHVlKTtcbiAgfVxuXG4gIHJlYWRvbmx5IGlzRGlzYWJsZWQgPSBjb21wdXRlZChcbiAgICAoKSA9PlxuICAgICAgdGhpcy5jb25zdW1lckRpc2FibGVkKCkgfHxcbiAgICAgICF0aGlzLnNuYXBzaG90KCk/LmNhbkFkdmFuY2UgfHxcbiAgICAgIHRoaXMuc3RlcCgpPy5wb3BvdmVyPy5kaXNhYmxlQWR2YW5jZUJ1dHRvbiA9PT0gdHJ1ZSxcbiAgKTtcbiAgcmVhZG9ubHkgbGFiZWwgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMuc25hcHNob3QoKT8uaXNMYXN0U3RlcFxuICAgICAgPyAodGhpcy5maW5pc2hMYWJlbFZhbHVlKCkgPz8gXCJGaW5pc2ggdG91clwiKVxuICAgICAgOiAodGhpcy5hZHZhbmNlTGFiZWxWYWx1ZSgpID8/IFwiQWR2YW5jZSBzdGVwXCIpO1xuICB9KTtcbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcImdsb3ctdG91ci1jYW5jZWwtdHJpZ2dlclwiLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICB0ZW1wbGF0ZTogYFxuICAgIEBpZiAoc25hcHNob3QoKT8uY2FuQ2FuY2VsKSB7XG4gICAgICA8YnV0dG9uXG4gICAgICAgIGRhdGEtZ2xvdy10b3VyLWNhbmNlbC10cmlnZ2VyXG4gICAgICAgIFthdHRyLmFyaWEtY29udHJvbHNdPVwiYXJpYUNvbnRyb2xzKClcIlxuICAgICAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cImlzRGlzYWJsZWQoKSA/ICd0cnVlJyA6ICdmYWxzZSdcIlxuICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbFRleHQoKSA/PyBsYWJlbCgpXCJcbiAgICAgICAgW2F0dHIuZGF0YS1nbG93LXRvdXItY29uc3VtZXItZGlzYWJsZWRdPVwiY29uc3VtZXJEaXNhYmxlZCgpID8gJ3RydWUnIDogbnVsbFwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkKClcIlxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgID48bmctY29udGVudD57eyBsYWJlbCgpIH19PC9uZy1jb250ZW50PjwvYnV0dG9uPlxuICAgIH1cbiAgYCxcbn0pXG4vKiogQnV0dG9uIGNvbXBvbmVudCBmb3IgY2FuY2VsaW5nL3NraXBwaW5nIHRoZSB0b3VyLiAqL1xuZXhwb3J0IGNsYXNzIEdsb3dUb3VyQ2FuY2VsVHJpZ2dlciBleHRlbmRzIEdsb3dUb3VyVHJpZ2dlciB7XG4gIC8qKiBPcHRpb25hbCBhcmlhLWxhYmVsIGZvciB0aGUgY2FuY2VsIGJ1dHRvbi4gKi9cbiAgQElucHV0KCkgc2V0IGFyaWFMYWJlbCh2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5zZXRBcmlhTGFiZWwodmFsdWUpO1xuICB9XG4gIC8qKiBXaGV0aGVyIHRoZSBidXR0b24gaXMgZGlzYWJsZWQuICovXG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KSBzZXQgZGlzYWJsZWQodmFsdWU6IGJvb2xlYW4pIHtcbiAgICB0aGlzLnNldERpc2FibGVkKHZhbHVlKTtcbiAgfVxuXG4gIHJlYWRvbmx5IGlzRGlzYWJsZWQgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmNvbnN1bWVyRGlzYWJsZWQoKSB8fCAhdGhpcy5zbmFwc2hvdCgpPy5jYW5DYW5jZWwpO1xuICByZWFkb25seSBsYWJlbCA9IGNvbXB1dGVkKCgpID0+IFwiU2tpcFwiKTtcbn1cbiJdfQ==
|