angular-debug-recorder 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/README.md +24 -0
- package/esm2022/angular-debug-recorder.mjs +5 -0
- package/esm2022/lib/action-list/action-list.component.mjs +220 -0
- package/esm2022/lib/debug-panel/debug-panel.component.mjs +516 -0
- package/esm2022/lib/models/recorded-action.model.mjs +2 -0
- package/esm2022/lib/services/ai-generator.service.mjs +61 -0
- package/esm2022/lib/services/recorder.service.mjs +354 -0
- package/esm2022/lib/services/rrweb-recorder.service.mjs +108 -0
- package/esm2022/lib/session-replay/session-replay.component.mjs +166 -0
- package/esm2022/lib/settings-dialog/settings-dialog.component.mjs +105 -0
- package/esm2022/lib/test-preview/test-preview.component.mjs +120 -0
- package/esm2022/public-api.mjs +17 -0
- package/fesm2022/angular-debug-recorder.mjs +1631 -0
- package/fesm2022/angular-debug-recorder.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/action-list/action-list.component.d.ts +21 -0
- package/lib/debug-panel/debug-panel.component.d.ts +38 -0
- package/lib/models/recorded-action.model.d.ts +45 -0
- package/lib/services/ai-generator.service.d.ts +20 -0
- package/lib/services/recorder.service.d.ts +46 -0
- package/lib/services/rrweb-recorder.service.d.ts +27 -0
- package/lib/session-replay/session-replay.component.d.ts +19 -0
- package/lib/settings-dialog/settings-dialog.component.d.ts +11 -0
- package/lib/test-preview/test-preview.component.d.ts +13 -0
- package/package.json +37 -0
- package/public-api.d.ts +9 -0
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# DebugRecorder
|
|
2
|
+
|
|
3
|
+
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.0.
|
|
4
|
+
|
|
5
|
+
## Code scaffolding
|
|
6
|
+
|
|
7
|
+
Run `ng generate component component-name --project debug-recorder` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project debug-recorder`.
|
|
8
|
+
> Note: Don't forget to add `--project debug-recorder` or else it will be added to the default project in your `angular.json` file.
|
|
9
|
+
|
|
10
|
+
## Build
|
|
11
|
+
|
|
12
|
+
Run `ng build debug-recorder` to build the project. The build artifacts will be stored in the `dist/` directory.
|
|
13
|
+
|
|
14
|
+
## Publishing
|
|
15
|
+
|
|
16
|
+
After building your library with `ng build debug-recorder`, go to the dist folder `cd dist/debug-recorder` and run `npm publish`.
|
|
17
|
+
|
|
18
|
+
## Running unit tests
|
|
19
|
+
|
|
20
|
+
Run `ng test debug-recorder` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
|
21
|
+
|
|
22
|
+
## Further help
|
|
23
|
+
|
|
24
|
+
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated bundle index. Do not edit.
|
|
3
|
+
*/
|
|
4
|
+
export * from './public-api';
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1kZWJ1Zy1yZWNvcmRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL2RlYnVnLXJlY29yZGVyL3NyYy9hbmd1bGFyLWRlYnVnLXJlY29yZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyxjQUFjLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdlbmVyYXRlZCBidW5kbGUgaW5kZXguIERvIG5vdCBlZGl0LlxuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vcHVibGljLWFwaSc7XG4iXX0=
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { Component, Input, Output, EventEmitter, signal } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { FormsModule } from '@angular/forms';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import * as i1 from "@angular/forms";
|
|
6
|
+
export class ActionListComponent {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.session = null;
|
|
9
|
+
this.removeAction = new EventEmitter();
|
|
10
|
+
this.addNote = new EventEmitter();
|
|
11
|
+
this.expandedId = signal(null);
|
|
12
|
+
this.noteMap = {};
|
|
13
|
+
}
|
|
14
|
+
toggleExpand(id) {
|
|
15
|
+
this.expandedId.update(v => v === id ? null : id);
|
|
16
|
+
}
|
|
17
|
+
onRemove(id, e) {
|
|
18
|
+
e.stopPropagation();
|
|
19
|
+
this.removeAction.emit(id);
|
|
20
|
+
}
|
|
21
|
+
onAddNote(id) {
|
|
22
|
+
this.addNote.emit({ id, note: this.noteMap[id] ?? '' });
|
|
23
|
+
}
|
|
24
|
+
getActionIcon(type) {
|
|
25
|
+
const icons = {
|
|
26
|
+
click: '👆',
|
|
27
|
+
dblclick: '👆👆',
|
|
28
|
+
input: '⌨️',
|
|
29
|
+
select: '📋',
|
|
30
|
+
submit: '📤',
|
|
31
|
+
navigation: '🔗',
|
|
32
|
+
keypress: '⌨️',
|
|
33
|
+
scroll: '↕️',
|
|
34
|
+
hover: '🖱️',
|
|
35
|
+
assertion: '✅',
|
|
36
|
+
screenshot: '📸',
|
|
37
|
+
};
|
|
38
|
+
return icons[type] ?? '•';
|
|
39
|
+
}
|
|
40
|
+
formatTime(ts) {
|
|
41
|
+
return new Date(ts).toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
|
42
|
+
}
|
|
43
|
+
formatDuration(start, end) {
|
|
44
|
+
const s = Math.round((end - start) / 1000);
|
|
45
|
+
return s < 60 ? `${s}s` : `${Math.floor(s / 60)}m ${s % 60}s`;
|
|
46
|
+
}
|
|
47
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ActionListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
48
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: ActionListComponent, isStandalone: true, selector: "app-action-list", inputs: { session: "session" }, outputs: { removeAction: "removeAction", addNote: "addNote" }, ngImport: i0, template: `
|
|
49
|
+
<div class="action-list" data-debug-panel>
|
|
50
|
+
@if (!session || session.actions.length === 0) {
|
|
51
|
+
<div class="empty-state">
|
|
52
|
+
<div class="empty-icon">🎬</div>
|
|
53
|
+
<p>Noch keine Aktionen aufgezeichnet.</p>
|
|
54
|
+
<p class="hint">Starte die Aufnahme und interagiere mit der App.</p>
|
|
55
|
+
<div class="shortcuts-hint">
|
|
56
|
+
<kbd>Ctrl+Shift+D</kbd> Panel
|
|
57
|
+
<kbd>Ctrl+Shift+R</kbd> Record
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
} @else {
|
|
61
|
+
<div class="list-header">
|
|
62
|
+
<span class="list-count">{{ session.actions.length }} Aktionen</span>
|
|
63
|
+
<span class="list-duration">
|
|
64
|
+
@if (session.endTime) {
|
|
65
|
+
{{ formatDuration(session.startTime, session.endTime) }}
|
|
66
|
+
} @else {
|
|
67
|
+
Live
|
|
68
|
+
}
|
|
69
|
+
</span>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
@for (action of session.actions; track action.id; let i = $index) {
|
|
73
|
+
<div class="action-item" [class.expanded]="expandedId() === action.id">
|
|
74
|
+
<div class="action-row" (click)="toggleExpand(action.id)">
|
|
75
|
+
<span class="action-index">{{ i + 1 }}</span>
|
|
76
|
+
<span class="action-type-badge" [class]="'type-' + action.type">
|
|
77
|
+
{{ getActionIcon(action.type) }}
|
|
78
|
+
</span>
|
|
79
|
+
<div class="action-info">
|
|
80
|
+
<span class="action-desc">{{ action.description }}</span>
|
|
81
|
+
<span class="action-selector">{{ action.selector }}</span>
|
|
82
|
+
</div>
|
|
83
|
+
<span class="action-time">{{ formatTime(action.timestamp) }}</span>
|
|
84
|
+
<button
|
|
85
|
+
class="remove-btn"
|
|
86
|
+
data-debug-panel
|
|
87
|
+
title="Aktion entfernen"
|
|
88
|
+
(click)="onRemove(action.id, $event)"
|
|
89
|
+
>✕</button>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
@if (expandedId() === action.id) {
|
|
93
|
+
<div class="action-detail" data-debug-panel>
|
|
94
|
+
<div class="detail-grid">
|
|
95
|
+
<span class="detail-label">Selector</span>
|
|
96
|
+
<code class="detail-value">{{ action.selector }}</code>
|
|
97
|
+
@if (action.value) {
|
|
98
|
+
<span class="detail-label">Wert</span>
|
|
99
|
+
<code class="detail-value">{{ action.value }}</code>
|
|
100
|
+
}
|
|
101
|
+
@if (action.element?.tagName) {
|
|
102
|
+
<span class="detail-label">Element</span>
|
|
103
|
+
<code class="detail-value"><{{ action.element?.tagName }}></code>
|
|
104
|
+
}
|
|
105
|
+
<span class="detail-label">Strategie</span>
|
|
106
|
+
<span class="detail-value strategy-badge" [class]="'strat-' + action.selectorStrategy">
|
|
107
|
+
{{ action.selectorStrategy }}
|
|
108
|
+
</span>
|
|
109
|
+
<span class="detail-label">URL</span>
|
|
110
|
+
<code class="detail-value url-val">{{ action.url }}</code>
|
|
111
|
+
</div>
|
|
112
|
+
<div class="note-area">
|
|
113
|
+
<textarea
|
|
114
|
+
data-debug-panel
|
|
115
|
+
class="note-input"
|
|
116
|
+
[(ngModel)]="noteMap[action.id]"
|
|
117
|
+
placeholder="Notiz zu dieser Aktion..."
|
|
118
|
+
rows="2"
|
|
119
|
+
(blur)="onAddNote(action.id)"
|
|
120
|
+
></textarea>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
}
|
|
124
|
+
</div>
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
</div>
|
|
128
|
+
`, isInline: true, styles: [".action-list{padding:0}.empty-state{text-align:center;padding:32px 20px;color:#64748b}.empty-icon{font-size:40px;margin-bottom:10px}.empty-state p{margin:4px 0;font-size:13px}.hint{font-size:11px;color:#475569}.shortcuts-hint{margin-top:12px;font-size:11px;color:#475569}kbd{background:#1e293b;border:1px solid #334155;color:#94a3b8;padding:2px 6px;border-radius:4px;font-size:10px}.list-header{display:flex;justify-content:space-between;padding:8px 14px;font-size:11px;color:#64748b;background:#0f172a;border-bottom:1px solid #1e293b;position:sticky;top:0}.action-item{border-bottom:1px solid #1e293b;transition:background .1s}.action-item:hover{background:#1e293b80}.action-item.expanded{background:#1e293b}.action-row{display:flex;align-items:center;padding:8px 10px;gap:8px;cursor:pointer}.action-index{color:#475569;font-size:10px;min-width:18px;text-align:right}.action-type-badge{font-size:14px;min-width:20px;text-align:center}.action-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}.action-desc{font-size:12px;color:#cbd5e1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.action-selector{font-size:10px;color:#64748b;font-family:Cascadia Code,Consolas,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.action-time{font-size:10px;color:#475569;white-space:nowrap}.remove-btn{background:none;border:none;color:#475569;cursor:pointer;font-size:12px;padding:2px 5px;border-radius:3px;opacity:0;transition:opacity .15s,color .15s}.action-row:hover .remove-btn{opacity:1}.remove-btn:hover{color:#f87171}.action-detail{padding:10px 14px;background:#0f172ab3;border-top:1px solid #1e293b}.detail-grid{display:grid;grid-template-columns:auto 1fr;gap:4px 10px;margin-bottom:8px;align-items:start}.detail-label{font-size:10px;color:#64748b;padding-top:2px;white-space:nowrap}.detail-value{font-size:11px;color:#93c5fd;font-family:Cascadia Code,Consolas,monospace;word-break:break-all}.url-val{color:#6ee7b7}.strategy-badge{font-size:10px;padding:1px 6px;border-radius:3px;font-family:monospace}.strat-data-testid,.strat-data-cy{background:#064e3b;color:#34d399}.strat-id{background:#1e3a8a;color:#93c5fd}.strat-name{background:#44337a;color:#c4b5fd}.strat-class{background:#374151;color:#9ca3af}.strat-combined{background:#292524;color:#d6d3d1}.note-area{margin-top:6px}.note-input{width:100%;box-sizing:border-box;background:#0f172a;border:1px solid #334155;color:#e2e8f0;border-radius:5px;padding:6px 8px;font-size:11px;resize:vertical}.note-input:focus{outline:none;border-color:#3b82f6}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); }
|
|
129
|
+
}
|
|
130
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ActionListComponent, decorators: [{
|
|
131
|
+
type: Component,
|
|
132
|
+
args: [{ selector: 'app-action-list', standalone: true, imports: [CommonModule, FormsModule], template: `
|
|
133
|
+
<div class="action-list" data-debug-panel>
|
|
134
|
+
@if (!session || session.actions.length === 0) {
|
|
135
|
+
<div class="empty-state">
|
|
136
|
+
<div class="empty-icon">🎬</div>
|
|
137
|
+
<p>Noch keine Aktionen aufgezeichnet.</p>
|
|
138
|
+
<p class="hint">Starte die Aufnahme und interagiere mit der App.</p>
|
|
139
|
+
<div class="shortcuts-hint">
|
|
140
|
+
<kbd>Ctrl+Shift+D</kbd> Panel
|
|
141
|
+
<kbd>Ctrl+Shift+R</kbd> Record
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
} @else {
|
|
145
|
+
<div class="list-header">
|
|
146
|
+
<span class="list-count">{{ session.actions.length }} Aktionen</span>
|
|
147
|
+
<span class="list-duration">
|
|
148
|
+
@if (session.endTime) {
|
|
149
|
+
{{ formatDuration(session.startTime, session.endTime) }}
|
|
150
|
+
} @else {
|
|
151
|
+
Live
|
|
152
|
+
}
|
|
153
|
+
</span>
|
|
154
|
+
</div>
|
|
155
|
+
|
|
156
|
+
@for (action of session.actions; track action.id; let i = $index) {
|
|
157
|
+
<div class="action-item" [class.expanded]="expandedId() === action.id">
|
|
158
|
+
<div class="action-row" (click)="toggleExpand(action.id)">
|
|
159
|
+
<span class="action-index">{{ i + 1 }}</span>
|
|
160
|
+
<span class="action-type-badge" [class]="'type-' + action.type">
|
|
161
|
+
{{ getActionIcon(action.type) }}
|
|
162
|
+
</span>
|
|
163
|
+
<div class="action-info">
|
|
164
|
+
<span class="action-desc">{{ action.description }}</span>
|
|
165
|
+
<span class="action-selector">{{ action.selector }}</span>
|
|
166
|
+
</div>
|
|
167
|
+
<span class="action-time">{{ formatTime(action.timestamp) }}</span>
|
|
168
|
+
<button
|
|
169
|
+
class="remove-btn"
|
|
170
|
+
data-debug-panel
|
|
171
|
+
title="Aktion entfernen"
|
|
172
|
+
(click)="onRemove(action.id, $event)"
|
|
173
|
+
>✕</button>
|
|
174
|
+
</div>
|
|
175
|
+
|
|
176
|
+
@if (expandedId() === action.id) {
|
|
177
|
+
<div class="action-detail" data-debug-panel>
|
|
178
|
+
<div class="detail-grid">
|
|
179
|
+
<span class="detail-label">Selector</span>
|
|
180
|
+
<code class="detail-value">{{ action.selector }}</code>
|
|
181
|
+
@if (action.value) {
|
|
182
|
+
<span class="detail-label">Wert</span>
|
|
183
|
+
<code class="detail-value">{{ action.value }}</code>
|
|
184
|
+
}
|
|
185
|
+
@if (action.element?.tagName) {
|
|
186
|
+
<span class="detail-label">Element</span>
|
|
187
|
+
<code class="detail-value"><{{ action.element?.tagName }}></code>
|
|
188
|
+
}
|
|
189
|
+
<span class="detail-label">Strategie</span>
|
|
190
|
+
<span class="detail-value strategy-badge" [class]="'strat-' + action.selectorStrategy">
|
|
191
|
+
{{ action.selectorStrategy }}
|
|
192
|
+
</span>
|
|
193
|
+
<span class="detail-label">URL</span>
|
|
194
|
+
<code class="detail-value url-val">{{ action.url }}</code>
|
|
195
|
+
</div>
|
|
196
|
+
<div class="note-area">
|
|
197
|
+
<textarea
|
|
198
|
+
data-debug-panel
|
|
199
|
+
class="note-input"
|
|
200
|
+
[(ngModel)]="noteMap[action.id]"
|
|
201
|
+
placeholder="Notiz zu dieser Aktion..."
|
|
202
|
+
rows="2"
|
|
203
|
+
(blur)="onAddNote(action.id)"
|
|
204
|
+
></textarea>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
}
|
|
208
|
+
</div>
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
</div>
|
|
212
|
+
`, styles: [".action-list{padding:0}.empty-state{text-align:center;padding:32px 20px;color:#64748b}.empty-icon{font-size:40px;margin-bottom:10px}.empty-state p{margin:4px 0;font-size:13px}.hint{font-size:11px;color:#475569}.shortcuts-hint{margin-top:12px;font-size:11px;color:#475569}kbd{background:#1e293b;border:1px solid #334155;color:#94a3b8;padding:2px 6px;border-radius:4px;font-size:10px}.list-header{display:flex;justify-content:space-between;padding:8px 14px;font-size:11px;color:#64748b;background:#0f172a;border-bottom:1px solid #1e293b;position:sticky;top:0}.action-item{border-bottom:1px solid #1e293b;transition:background .1s}.action-item:hover{background:#1e293b80}.action-item.expanded{background:#1e293b}.action-row{display:flex;align-items:center;padding:8px 10px;gap:8px;cursor:pointer}.action-index{color:#475569;font-size:10px;min-width:18px;text-align:right}.action-type-badge{font-size:14px;min-width:20px;text-align:center}.action-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}.action-desc{font-size:12px;color:#cbd5e1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.action-selector{font-size:10px;color:#64748b;font-family:Cascadia Code,Consolas,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.action-time{font-size:10px;color:#475569;white-space:nowrap}.remove-btn{background:none;border:none;color:#475569;cursor:pointer;font-size:12px;padding:2px 5px;border-radius:3px;opacity:0;transition:opacity .15s,color .15s}.action-row:hover .remove-btn{opacity:1}.remove-btn:hover{color:#f87171}.action-detail{padding:10px 14px;background:#0f172ab3;border-top:1px solid #1e293b}.detail-grid{display:grid;grid-template-columns:auto 1fr;gap:4px 10px;margin-bottom:8px;align-items:start}.detail-label{font-size:10px;color:#64748b;padding-top:2px;white-space:nowrap}.detail-value{font-size:11px;color:#93c5fd;font-family:Cascadia Code,Consolas,monospace;word-break:break-all}.url-val{color:#6ee7b7}.strategy-badge{font-size:10px;padding:1px 6px;border-radius:3px;font-family:monospace}.strat-data-testid,.strat-data-cy{background:#064e3b;color:#34d399}.strat-id{background:#1e3a8a;color:#93c5fd}.strat-name{background:#44337a;color:#c4b5fd}.strat-class{background:#374151;color:#9ca3af}.strat-combined{background:#292524;color:#d6d3d1}.note-area{margin-top:6px}.note-input{width:100%;box-sizing:border-box;background:#0f172a;border:1px solid #334155;color:#e2e8f0;border-radius:5px;padding:6px 8px;font-size:11px;resize:vertical}.note-input:focus{outline:none;border-color:#3b82f6}\n"] }]
|
|
213
|
+
}], propDecorators: { session: [{
|
|
214
|
+
type: Input
|
|
215
|
+
}], removeAction: [{
|
|
216
|
+
type: Output
|
|
217
|
+
}], addNote: [{
|
|
218
|
+
type: Output
|
|
219
|
+
}] } });
|
|
220
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWN0aW9uLWxpc3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZGVidWctcmVjb3JkZXIvc3JjL2xpYi9hY3Rpb24tbGlzdC9hY3Rpb24tbGlzdC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDL0UsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7O0FBK083QyxNQUFNLE9BQU8sbUJBQW1CO0lBNU9oQztRQTZPVyxZQUFPLEdBQTRCLElBQUksQ0FBQztRQUN2QyxpQkFBWSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFDMUMsWUFBTyxHQUFHLElBQUksWUFBWSxFQUFnQyxDQUFDO1FBRXJFLGVBQVUsR0FBRyxNQUFNLENBQWdCLElBQUksQ0FBQyxDQUFDO1FBQ3pDLFlBQU8sR0FBMkIsRUFBRSxDQUFDO0tBd0N0QztJQXRDQyxZQUFZLENBQUMsRUFBVTtRQUNyQixJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDcEQsQ0FBQztJQUVELFFBQVEsQ0FBQyxFQUFVLEVBQUUsQ0FBUTtRQUMzQixDQUFDLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDcEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVELFNBQVMsQ0FBQyxFQUFVO1FBQ2xCLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVELGFBQWEsQ0FBQyxJQUFZO1FBQ3hCLE1BQU0sS0FBSyxHQUEyQjtZQUNwQyxLQUFLLEVBQVEsSUFBSTtZQUNqQixRQUFRLEVBQUssTUFBTTtZQUNuQixLQUFLLEVBQVEsSUFBSTtZQUNqQixNQUFNLEVBQU8sSUFBSTtZQUNqQixNQUFNLEVBQU8sSUFBSTtZQUNqQixVQUFVLEVBQUcsSUFBSTtZQUNqQixRQUFRLEVBQUssSUFBSTtZQUNqQixNQUFNLEVBQU8sSUFBSTtZQUNqQixLQUFLLEVBQVEsS0FBSztZQUNsQixTQUFTLEVBQUksR0FBRztZQUNoQixVQUFVLEVBQUcsSUFBSTtTQUNsQixDQUFDO1FBQ0YsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxDQUFDO0lBQzVCLENBQUM7SUFFRCxVQUFVLENBQUMsRUFBVTtRQUNuQixPQUFPLElBQUksSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLE9BQU8sRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUM3RyxDQUFDO0lBRUQsY0FBYyxDQUFDLEtBQWEsRUFBRSxHQUFXO1FBQ3ZDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFDM0MsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBQyxFQUFFLEdBQUcsQ0FBQztJQUM1RCxDQUFDOytHQTdDVSxtQkFBbUI7bUdBQW5CLG1CQUFtQiwwS0F4T3BCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWdGVCxvakZBakZTLFlBQVksOEJBQUUsV0FBVzs7NEZBeU94QixtQkFBbUI7a0JBNU8vQixTQUFTOytCQUNFLGlCQUFpQixjQUNmLElBQUksV0FDUCxDQUFDLFlBQVksRUFBRSxXQUFXLENBQUMsWUFDMUI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBZ0ZUOzhCQXlKUSxPQUFPO3NCQUFmLEtBQUs7Z0JBQ0ksWUFBWTtzQkFBckIsTUFBTTtnQkFDRyxPQUFPO3NCQUFoQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIHNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgUmVjb3JkZWRBY3Rpb24sIFJlY29yZGluZ1Nlc3Npb24gfSBmcm9tICcuLi9tb2RlbHMvcmVjb3JkZWQtYWN0aW9uLm1vZGVsJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLWFjdGlvbi1saXN0JyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgRm9ybXNNb2R1bGVdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJhY3Rpb24tbGlzdFwiIGRhdGEtZGVidWctcGFuZWw+XG4gICAgICBAaWYgKCFzZXNzaW9uIHx8IHNlc3Npb24uYWN0aW9ucy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgPGRpdiBjbGFzcz1cImVtcHR5LXN0YXRlXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImVtcHR5LWljb25cIj7wn46sPC9kaXY+XG4gICAgICAgICAgPHA+Tm9jaCBrZWluZSBBa3Rpb25lbiBhdWZnZXplaWNobmV0LjwvcD5cbiAgICAgICAgICA8cCBjbGFzcz1cImhpbnRcIj5TdGFydGUgZGllIEF1Zm5haG1lIHVuZCBpbnRlcmFnaWVyZSBtaXQgZGVyIEFwcC48L3A+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInNob3J0Y3V0cy1oaW50XCI+XG4gICAgICAgICAgICA8a2JkPkN0cmwrU2hpZnQrRDwva2JkPiBQYW5lbCAmbmJzcDtcbiAgICAgICAgICAgIDxrYmQ+Q3RybCtTaGlmdCtSPC9rYmQ+IFJlY29yZFxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIH0gQGVsc2Uge1xuICAgICAgICA8ZGl2IGNsYXNzPVwibGlzdC1oZWFkZXJcIj5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImxpc3QtY291bnRcIj57eyBzZXNzaW9uLmFjdGlvbnMubGVuZ3RoIH19IEFrdGlvbmVuPC9zcGFuPlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwibGlzdC1kdXJhdGlvblwiPlxuICAgICAgICAgICAgQGlmIChzZXNzaW9uLmVuZFRpbWUpIHtcbiAgICAgICAgICAgICAge3sgZm9ybWF0RHVyYXRpb24oc2Vzc2lvbi5zdGFydFRpbWUsIHNlc3Npb24uZW5kVGltZSkgfX1cbiAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICBMaXZlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9zcGFuPlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICBAZm9yIChhY3Rpb24gb2Ygc2Vzc2lvbi5hY3Rpb25zOyB0cmFjayBhY3Rpb24uaWQ7IGxldCBpID0gJGluZGV4KSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImFjdGlvbi1pdGVtXCIgW2NsYXNzLmV4cGFuZGVkXT1cImV4cGFuZGVkSWQoKSA9PT0gYWN0aW9uLmlkXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWN0aW9uLXJvd1wiIChjbGljayk9XCJ0b2dnbGVFeHBhbmQoYWN0aW9uLmlkKVwiPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImFjdGlvbi1pbmRleFwiPnt7IGkgKyAxIH19PC9zcGFuPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImFjdGlvbi10eXBlLWJhZGdlXCIgW2NsYXNzXT1cIid0eXBlLScgKyBhY3Rpb24udHlwZVwiPlxuICAgICAgICAgICAgICAgIHt7IGdldEFjdGlvbkljb24oYWN0aW9uLnR5cGUpIH19XG4gICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImFjdGlvbi1pbmZvXCI+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJhY3Rpb24tZGVzY1wiPnt7IGFjdGlvbi5kZXNjcmlwdGlvbiB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImFjdGlvbi1zZWxlY3RvclwiPnt7IGFjdGlvbi5zZWxlY3RvciB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWN0aW9uLXRpbWVcIj57eyBmb3JtYXRUaW1lKGFjdGlvbi50aW1lc3RhbXApIH19PC9zcGFuPlxuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJyZW1vdmUtYnRuXCJcbiAgICAgICAgICAgICAgICBkYXRhLWRlYnVnLXBhbmVsXG4gICAgICAgICAgICAgICAgdGl0bGU9XCJBa3Rpb24gZW50ZmVybmVuXCJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwib25SZW1vdmUoYWN0aW9uLmlkLCAkZXZlbnQpXCJcbiAgICAgICAgICAgICAgPuKclTwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIEBpZiAoZXhwYW5kZWRJZCgpID09PSBhY3Rpb24uaWQpIHtcbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImFjdGlvbi1kZXRhaWxcIiBkYXRhLWRlYnVnLXBhbmVsPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkZXRhaWwtZ3JpZFwiPlxuICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJkZXRhaWwtbGFiZWxcIj5TZWxlY3Rvcjwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIDxjb2RlIGNsYXNzPVwiZGV0YWlsLXZhbHVlXCI+e3sgYWN0aW9uLnNlbGVjdG9yIH19PC9jb2RlPlxuICAgICAgICAgICAgICAgICAgQGlmIChhY3Rpb24udmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJkZXRhaWwtbGFiZWxcIj5XZXJ0PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8Y29kZSBjbGFzcz1cImRldGFpbC12YWx1ZVwiPnt7IGFjdGlvbi52YWx1ZSB9fTwvY29kZT5cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIEBpZiAoYWN0aW9uLmVsZW1lbnQ/LnRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJkZXRhaWwtbGFiZWxcIj5FbGVtZW50PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8Y29kZSBjbGFzcz1cImRldGFpbC12YWx1ZVwiPiZsdDt7eyBhY3Rpb24uZWxlbWVudD8udGFnTmFtZSB9fSZndDs8L2NvZGU+XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImRldGFpbC1sYWJlbFwiPlN0cmF0ZWdpZTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZGV0YWlsLXZhbHVlIHN0cmF0ZWd5LWJhZGdlXCIgW2NsYXNzXT1cIidzdHJhdC0nICsgYWN0aW9uLnNlbGVjdG9yU3RyYXRlZ3lcIj5cbiAgICAgICAgICAgICAgICAgICAge3sgYWN0aW9uLnNlbGVjdG9yU3RyYXRlZ3kgfX1cbiAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZGV0YWlsLWxhYmVsXCI+VVJMPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgPGNvZGUgY2xhc3M9XCJkZXRhaWwtdmFsdWUgdXJsLXZhbFwiPnt7IGFjdGlvbi51cmwgfX08L2NvZGU+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5vdGUtYXJlYVwiPlxuICAgICAgICAgICAgICAgICAgPHRleHRhcmVhXG4gICAgICAgICAgICAgICAgICAgIGRhdGEtZGVidWctcGFuZWxcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJub3RlLWlucHV0XCJcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJub3RlTWFwW2FjdGlvbi5pZF1cIlxuICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIk5vdGl6IHp1IGRpZXNlciBBa3Rpb24uLi5cIlxuICAgICAgICAgICAgICAgICAgICByb3dzPVwiMlwiXG4gICAgICAgICAgICAgICAgICAgIChibHVyKT1cIm9uQWRkTm90ZShhY3Rpb24uaWQpXCJcbiAgICAgICAgICAgICAgICAgID48L3RleHRhcmVhPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuICAgICAgfVxuICAgIDwvZGl2PlxuICBgLFxuICBzdHlsZXM6IFtgXG4gICAgLmFjdGlvbi1saXN0IHsgcGFkZGluZzogMDsgfVxuXG4gICAgLmVtcHR5LXN0YXRlIHtcbiAgICAgIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgICAgIHBhZGRpbmc6IDMycHggMjBweDtcbiAgICAgIGNvbG9yOiAjNjQ3NDhiO1xuICAgIH1cbiAgICAuZW1wdHktaWNvbiB7IGZvbnQtc2l6ZTogNDBweDsgbWFyZ2luLWJvdHRvbTogMTBweDsgfVxuICAgIC5lbXB0eS1zdGF0ZSBwIHsgbWFyZ2luOiA0cHggMDsgZm9udC1zaXplOiAxM3B4OyB9XG4gICAgLmhpbnQgeyBmb250LXNpemU6IDExcHg7IGNvbG9yOiAjNDc1NTY5OyB9XG4gICAgLnNob3J0Y3V0cy1oaW50IHtcbiAgICAgIG1hcmdpbi10b3A6IDEycHg7XG4gICAgICBmb250LXNpemU6IDExcHg7XG4gICAgICBjb2xvcjogIzQ3NTU2OTtcbiAgICB9XG4gICAga2JkIHtcbiAgICAgIGJhY2tncm91bmQ6ICMxZTI5M2I7XG4gICAgICBib3JkZXI6IDFweCBzb2xpZCAjMzM0MTU1O1xuICAgICAgY29sb3I6ICM5NGEzYjg7XG4gICAgICBwYWRkaW5nOiAycHggNnB4O1xuICAgICAgYm9yZGVyLXJhZGl1czogNHB4O1xuICAgICAgZm9udC1zaXplOiAxMHB4O1xuICAgIH1cblxuICAgIC5saXN0LWhlYWRlciB7XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICAgICAgcGFkZGluZzogOHB4IDE0cHg7XG4gICAgICBmb250LXNpemU6IDExcHg7XG4gICAgICBjb2xvcjogIzY0NzQ4YjtcbiAgICAgIGJhY2tncm91bmQ6ICMwZjE3MmE7XG4gICAgICBib3JkZXItYm90dG9tOiAxcHggc29saWQgIzFlMjkzYjtcbiAgICAgIHBvc2l0aW9uOiBzdGlja3k7XG4gICAgICB0b3A6IDA7XG4gICAgfVxuXG4gICAgLmFjdGlvbi1pdGVtIHtcbiAgICAgIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjMWUyOTNiO1xuICAgICAgdHJhbnNpdGlvbjogYmFja2dyb3VuZCAwLjFzO1xuICAgIH1cbiAgICAuYWN0aW9uLWl0ZW06aG92ZXIgeyBiYWNrZ3JvdW5kOiByZ2JhKDMwLDQxLDU5LDAuNSk7IH1cbiAgICAuYWN0aW9uLWl0ZW0uZXhwYW5kZWQgeyBiYWNrZ3JvdW5kOiAjMWUyOTNiOyB9XG5cbiAgICAuYWN0aW9uLXJvdyB7XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgIHBhZGRpbmc6IDhweCAxMHB4O1xuICAgICAgZ2FwOiA4cHg7XG4gICAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgfVxuICAgIC5hY3Rpb24taW5kZXgge1xuICAgICAgY29sb3I6ICM0NzU1Njk7XG4gICAgICBmb250LXNpemU6IDEwcHg7XG4gICAgICBtaW4td2lkdGg6IDE4cHg7XG4gICAgICB0ZXh0LWFsaWduOiByaWdodDtcbiAgICB9XG4gICAgLmFjdGlvbi10eXBlLWJhZGdlIHtcbiAgICAgIGZvbnQtc2l6ZTogMTRweDtcbiAgICAgIG1pbi13aWR0aDogMjBweDtcbiAgICAgIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgICB9XG4gICAgLmFjdGlvbi1pbmZvIHtcbiAgICAgIGZsZXg6IDE7XG4gICAgICBtaW4td2lkdGg6IDA7XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICAgIGdhcDogMXB4O1xuICAgIH1cbiAgICAuYWN0aW9uLWRlc2Mge1xuICAgICAgZm9udC1zaXplOiAxMnB4O1xuICAgICAgY29sb3I6ICNjYmQ1ZTE7XG4gICAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgICAgIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xuICAgIH1cbiAgICAuYWN0aW9uLXNlbGVjdG9yIHtcbiAgICAgIGZvbnQtc2l6ZTogMTBweDtcbiAgICAgIGNvbG9yOiAjNjQ3NDhiO1xuICAgICAgZm9udC1mYW1pbHk6ICdDYXNjYWRpYSBDb2RlJywgJ0NvbnNvbGFzJywgbW9ub3NwYWNlO1xuICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcbiAgICB9XG4gICAgLmFjdGlvbi10aW1lIHtcbiAgICAgIGZvbnQtc2l6ZTogMTBweDtcbiAgICAgIGNvbG9yOiAjNDc1NTY5O1xuICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgICB9XG4gICAgLnJlbW92ZS1idG4ge1xuICAgICAgYmFja2dyb3VuZDogbm9uZTtcbiAgICAgIGJvcmRlcjogbm9uZTtcbiAgICAgIGNvbG9yOiAjNDc1NTY5O1xuICAgICAgY3Vyc29yOiBwb2ludGVyO1xuICAgICAgZm9udC1zaXplOiAxMnB4O1xuICAgICAgcGFkZGluZzogMnB4IDVweDtcbiAgICAgIGJvcmRlci1yYWRpdXM6IDNweDtcbiAgICAgIG9wYWNpdHk6IDA7XG4gICAgICB0cmFuc2l0aW9uOiBvcGFjaXR5IDAuMTVzLCBjb2xvciAwLjE1cztcbiAgICB9XG4gICAgLmFjdGlvbi1yb3c6aG92ZXIgLnJlbW92ZS1idG4geyBvcGFjaXR5OiAxOyB9XG4gICAgLnJlbW92ZS1idG46aG92ZXIgeyBjb2xvcjogI2Y4NzE3MTsgfVxuXG4gICAgLmFjdGlvbi1kZXRhaWwge1xuICAgICAgcGFkZGluZzogMTBweCAxNHB4O1xuICAgICAgYmFja2dyb3VuZDogcmdiYSgxNSwyMyw0MiwwLjcpO1xuICAgICAgYm9yZGVyLXRvcDogMXB4IHNvbGlkICMxZTI5M2I7XG4gICAgfVxuICAgIC5kZXRhaWwtZ3JpZCB7XG4gICAgICBkaXNwbGF5OiBncmlkO1xuICAgICAgZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zOiBhdXRvIDFmcjtcbiAgICAgIGdhcDogNHB4IDEwcHg7XG4gICAgICBtYXJnaW4tYm90dG9tOiA4cHg7XG4gICAgICBhbGlnbi1pdGVtczogc3RhcnQ7XG4gICAgfVxuICAgIC5kZXRhaWwtbGFiZWwgeyBmb250LXNpemU6IDEwcHg7IGNvbG9yOiAjNjQ3NDhiOyBwYWRkaW5nLXRvcDogMnB4OyB3aGl0ZS1zcGFjZTogbm93cmFwOyB9XG4gICAgLmRldGFpbC12YWx1ZSB7XG4gICAgICBmb250LXNpemU6IDExcHg7XG4gICAgICBjb2xvcjogIzkzYzVmZDtcbiAgICAgIGZvbnQtZmFtaWx5OiAnQ2FzY2FkaWEgQ29kZScsICdDb25zb2xhcycsIG1vbm9zcGFjZTtcbiAgICAgIHdvcmQtYnJlYWs6IGJyZWFrLWFsbDtcbiAgICB9XG4gICAgLnVybC12YWwgeyBjb2xvcjogIzZlZTdiNzsgfVxuICAgIC5zdHJhdGVneS1iYWRnZSB7XG4gICAgICBmb250LXNpemU6IDEwcHg7XG4gICAgICBwYWRkaW5nOiAxcHggNnB4O1xuICAgICAgYm9yZGVyLXJhZGl1czogM3B4O1xuICAgICAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTtcbiAgICB9XG4gICAgLnN0cmF0LWRhdGEtdGVzdGlkIHsgYmFja2dyb3VuZDogIzA2NGUzYjsgY29sb3I6ICMzNGQzOTk7IH1cbiAgICAuc3RyYXQtZGF0YS1jeSAgICAgeyBiYWNrZ3JvdW5kOiAjMDY0ZTNiOyBjb2xvcjogIzM0ZDM5OTsgfVxuICAgIC5zdHJhdC1pZCAgICAgICAgICB7IGJhY2tncm91bmQ6ICMxZTNhOGE7IGNvbG9yOiAjOTNjNWZkOyB9XG4gICAgLnN0cmF0LW5hbWUgICAgICAgIHsgYmFja2dyb3VuZDogIzQ0MzM3YTsgY29sb3I6ICNjNGI1ZmQ7IH1cbiAgICAuc3RyYXQtY2xhc3MgICAgICAgeyBiYWNrZ3JvdW5kOiAjMzc0MTUxOyBjb2xvcjogIzljYTNhZjsgfVxuICAgIC5zdHJhdC1jb21iaW5lZCAgICB7IGJhY2tncm91bmQ6ICMyOTI1MjQ7IGNvbG9yOiAjZDZkM2QxOyB9XG5cbiAgICAubm90ZS1hcmVhIHsgbWFyZ2luLXRvcDogNnB4OyB9XG4gICAgLm5vdGUtaW5wdXQge1xuICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICAgICAgYmFja2dyb3VuZDogIzBmMTcyYTtcbiAgICAgIGJvcmRlcjogMXB4IHNvbGlkICMzMzQxNTU7XG4gICAgICBjb2xvcjogI2UyZThmMDtcbiAgICAgIGJvcmRlci1yYWRpdXM6IDVweDtcbiAgICAgIHBhZGRpbmc6IDZweCA4cHg7XG4gICAgICBmb250LXNpemU6IDExcHg7XG4gICAgICByZXNpemU6IHZlcnRpY2FsO1xuICAgIH1cbiAgICAubm90ZS1pbnB1dDpmb2N1cyB7IG91dGxpbmU6IG5vbmU7IGJvcmRlci1jb2xvcjogIzNiODJmNjsgfVxuICBgXSxcbn0pXG5leHBvcnQgY2xhc3MgQWN0aW9uTGlzdENvbXBvbmVudCB7XG4gIEBJbnB1dCgpIHNlc3Npb246IFJlY29yZGluZ1Nlc3Npb24gfCBudWxsID0gbnVsbDtcbiAgQE91dHB1dCgpIHJlbW92ZUFjdGlvbiA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuICBAT3V0cHV0KCkgYWRkTm90ZSA9IG5ldyBFdmVudEVtaXR0ZXI8eyBpZDogc3RyaW5nOyBub3RlOiBzdHJpbmcgfT4oKTtcblxuICBleHBhbmRlZElkID0gc2lnbmFsPHN0cmluZyB8IG51bGw+KG51bGwpO1xuICBub3RlTWFwOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cbiAgdG9nZ2xlRXhwYW5kKGlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmV4cGFuZGVkSWQudXBkYXRlKHYgPT4gdiA9PT0gaWQgPyBudWxsIDogaWQpO1xuICB9XG5cbiAgb25SZW1vdmUoaWQ6IHN0cmluZywgZTogRXZlbnQpOiB2b2lkIHtcbiAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIHRoaXMucmVtb3ZlQWN0aW9uLmVtaXQoaWQpO1xuICB9XG5cbiAgb25BZGROb3RlKGlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmFkZE5vdGUuZW1pdCh7IGlkLCBub3RlOiB0aGlzLm5vdGVNYXBbaWRdID8/ICcnIH0pO1xuICB9XG5cbiAgZ2V0QWN0aW9uSWNvbih0eXBlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGljb25zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgICAgY2xpY2s6ICAgICAgICfwn5GGJyxcbiAgICAgIGRibGNsaWNrOiAgICAn8J+RhvCfkYYnLFxuICAgICAgaW5wdXQ6ICAgICAgICfijKjvuI8nLFxuICAgICAgc2VsZWN0OiAgICAgICfwn5OLJyxcbiAgICAgIHN1Ym1pdDogICAgICAn8J+TpCcsXG4gICAgICBuYXZpZ2F0aW9uOiAgJ/CflJcnLFxuICAgICAga2V5cHJlc3M6ICAgICfijKjvuI8nLFxuICAgICAgc2Nyb2xsOiAgICAgICfihpXvuI8nLFxuICAgICAgaG92ZXI6ICAgICAgICfwn5ax77iPJyxcbiAgICAgIGFzc2VydGlvbjogICAn4pyFJyxcbiAgICAgIHNjcmVlbnNob3Q6ICAn8J+TuCcsXG4gICAgfTtcbiAgICByZXR1cm4gaWNvbnNbdHlwZV0gPz8gJ+KAoic7XG4gIH1cblxuICBmb3JtYXRUaW1lKHRzOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIHJldHVybiBuZXcgRGF0ZSh0cykudG9Mb2NhbGVUaW1lU3RyaW5nKCdkZS1ERScsIHsgaG91cjogJzItZGlnaXQnLCBtaW51dGU6ICcyLWRpZ2l0Jywgc2Vjb25kOiAnMi1kaWdpdCcgfSk7XG4gIH1cblxuICBmb3JtYXREdXJhdGlvbihzdGFydDogbnVtYmVyLCBlbmQ6IG51bWJlcik6IHN0cmluZyB7XG4gICAgY29uc3QgcyA9IE1hdGgucm91bmQoKGVuZCAtIHN0YXJ0KSAvIDEwMDApO1xuICAgIHJldHVybiBzIDwgNjAgPyBgJHtzfXNgIDogYCR7TWF0aC5mbG9vcihzLzYwKX1tICR7cyU2MH1zYDtcbiAgfVxufVxuIl19
|