@openelement/ui 0.41.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +78 -0
  3. package/package.json +142 -0
  4. package/src/daisy-classes.d.ts +7 -0
  5. package/src/daisy-classes.js +770 -0
  6. package/src/index.d.ts +57 -0
  7. package/src/index.js +62 -0
  8. package/src/manifest.d.ts +8 -0
  9. package/src/manifest.js +255 -0
  10. package/src/open-badge.d.ts +15 -0
  11. package/src/open-badge.js +88 -0
  12. package/src/open-brand-mark.d.ts +14 -0
  13. package/src/open-brand-mark.js +107 -0
  14. package/src/open-button.d.ts +38 -0
  15. package/src/open-button.js +219 -0
  16. package/src/open-callout.d.ts +26 -0
  17. package/src/open-callout.js +99 -0
  18. package/src/open-card.d.ts +33 -0
  19. package/src/open-card.js +107 -0
  20. package/src/open-code-block.d.ts +44 -0
  21. package/src/open-code-block.js +267 -0
  22. package/src/open-dialog.d.ts +47 -0
  23. package/src/open-dialog.js +235 -0
  24. package/src/open-dropdown.d.ts +25 -0
  25. package/src/open-dropdown.js +45 -0
  26. package/src/open-hero-ping.d.ts +27 -0
  27. package/src/open-hero-ping.js +136 -0
  28. package/src/open-input.d.ts +51 -0
  29. package/src/open-input.js +233 -0
  30. package/src/open-lab-panel.d.ts +16 -0
  31. package/src/open-lab-panel.js +151 -0
  32. package/src/open-lab-stage.d.ts +15 -0
  33. package/src/open-lab-stage.js +622 -0
  34. package/src/open-layout.d.ts +111 -0
  35. package/src/open-layout.js +1377 -0
  36. package/src/open-modal.d.ts +25 -0
  37. package/src/open-modal.js +48 -0
  38. package/src/open-props-tokens.d.ts +7 -0
  39. package/src/open-props-tokens.js +474 -0
  40. package/src/open-standards-visual.d.ts +20 -0
  41. package/src/open-standards-visual.js +425 -0
  42. package/src/open-step-card.d.ts +34 -0
  43. package/src/open-step-card.js +117 -0
  44. package/src/open-tabs.d.ts +27 -0
  45. package/src/open-tabs.js +56 -0
  46. package/src/open-theme-toggle.d.ts +38 -0
  47. package/src/open-theme-toggle.js +223 -0
@@ -0,0 +1,1377 @@
1
+ /** @jsxImportSource @openelement/core */ /**
2
+ * @openelement/ui - open-layout
3
+ *
4
+ * App layout component with header, sidebar, and footer.
5
+ * Web Standards Lab: light-first, restrained, documentation-focused.
6
+ *
7
+ * v0.20.0: Migrated from DsdLitElement to DsdElement (Ocean component).
8
+ * - CSSStyleSheet replaces Lit css``
9
+ * - render() returns string
10
+ * - @click bindings for mobile menu toggle
11
+ * - SPA navigation via Navigation API (navigate/fetch/swap) preserved
12
+ * - Event delegation at shadow root level for nav clicks
13
+ * v0.24.1: Migrated from html`` template to JSX (ADR-0057).
14
+ *
15
+ * @csspart container - The app-layout root div
16
+ * @csspart header - The sticky header element
17
+ * @csspart sidebar - The docs-sidebar nav
18
+ * @csspart main - The layout-main element
19
+ * @csspart footer - The app-footer element
20
+ * @csspart nav - The header-nav element
21
+ * @csspart nav-toggle - The mobile menu toggle button
22
+ *
23
+ * Usage:
24
+ * ```html
25
+ * <open-layout current-path="/guide/getting-started"
26
+ * nav-items='[{"section":"Guide","items":[{"path":"/guide/getting-started","label":"Getting Started"}]}]'>
27
+ * </open-layout>
28
+ * ```
29
+ */ import { OpenElement } from '@openelement/element';
30
+ import { StyleSheet } from '@openelement/core/style-sheet';
31
+ import { createContext, provideContext } from '@openelement/core';
32
+ import { escapeAttr, escapeHtml } from '@openelement/core';
33
+ import { createLogger } from '@openelement/core/logger';
34
+ import '.\/open-theme-toggle.js';
35
+ import './open-brand-mark.js';
36
+ export const tagName = 'open-layout';
37
+ const SAFE_URL_SCHEMES = new Set([
38
+ 'http:',
39
+ 'https:',
40
+ 'mailto:',
41
+ 'tel:',
42
+ 'sms:'
43
+ ]);
44
+ const log = createLogger('ui');
45
+ function isSafeLayoutUrl(url) {
46
+ const trimmed = url.trim();
47
+ if (!trimmed) return false;
48
+ if (trimmed.startsWith('//')) return false;
49
+ if (trimmed.startsWith('/') || trimmed.startsWith('#') || trimmed.startsWith('./') || trimmed.startsWith('../')) {
50
+ return true;
51
+ }
52
+ try {
53
+ const parsed = new URL(trimmed, 'https://openelement.org/');
54
+ return SAFE_URL_SCHEMES.has(parsed.protocol);
55
+ } catch {
56
+ return false;
57
+ }
58
+ }
59
+ /* --- Locale/path helpers (inlined from @openelement/router) --- */ const LOCALE_LABELS = {
60
+ en: '中文',
61
+ zh: 'English'
62
+ };
63
+ function parsePathWithoutLocale(pathname, locales) {
64
+ const segs = pathname.split('/').filter(Boolean);
65
+ if (segs.length > 0 && locales.includes(segs[0])) {
66
+ return '/' + segs.slice(1).join('/') || '/';
67
+ }
68
+ return pathname || '/';
69
+ }
70
+ function detectLocale(pathname, locales, defaultLocale) {
71
+ const segs = pathname.split('/').filter(Boolean);
72
+ if (segs.length > 0 && locales.includes(segs[0])) return segs[0];
73
+ return defaultLocale;
74
+ }
75
+ function localizePath(path1, locale) {
76
+ if (isSafeLayoutUrl(path1) && /^https?:/i.test(path1)) return path1;
77
+ return `/${locale}${path1}`;
78
+ }
79
+ function switchPath(currentPath, currentLocale, locales) {
80
+ const other = locales.find((l)=>l !== currentLocale) || currentLocale;
81
+ return `/${other}${currentPath}`;
82
+ }
83
+ function switchLabel(currentLocale) {
84
+ return LOCALE_LABELS[currentLocale] || currentLocale;
85
+ }
86
+ /** SignalContext key: theme state shared across all components */ export const THEME_CTX = createContext(Symbol('theme'), 'light');
87
+ const sheet = new StyleSheet();
88
+ sheet.replaceSync(`
89
+ :host {
90
+ display: block;
91
+ }
92
+
93
+ * { font-family: var(--font-sans); }
94
+
95
+ .app-layout {
96
+ display: flex;
97
+ flex-direction: column;
98
+ min-height: 100vh;
99
+ background: var(--bg-base);
100
+ color: var(--text-primary);
101
+ font-family: var(--font-sans);
102
+ -webkit-font-smoothing: antialiased;
103
+ -moz-osx-font-smoothing: grayscale;
104
+ }
105
+
106
+ .layout-body {
107
+ display: flex;
108
+ flex: 1;
109
+ max-width: 1400px;
110
+ margin: 0 auto;
111
+ width: 100%;
112
+ }
113
+
114
+ .layout-main {
115
+ flex: 1;
116
+ min-width: 0;
117
+ width: 100%;
118
+ }
119
+
120
+ .app-layout[home] .layout-body,
121
+ .app-layout[full-width] .layout-body {
122
+ display: flex;
123
+ flex-direction: column;
124
+ max-width: none;
125
+ }
126
+
127
+ .app-layout[home] .layout-main,
128
+ .app-layout[full-width] .layout-main {
129
+ flex: 1;
130
+ }
131
+
132
+ /* Header */
133
+ .app-header {
134
+ position: sticky;
135
+ top: 0;
136
+ z-index: 100;
137
+ background: var(--nav-bg);
138
+ border-bottom: var(--border-size-1) solid var(--border);
139
+ backdrop-filter: blur(18px) saturate(150%);
140
+ -webkit-backdrop-filter: blur(18px) saturate(150%);
141
+ transition: background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
142
+ }
143
+ .app-header.scrolled {
144
+ background: color-mix(in srgb, var(--bg-base) 88%, transparent);
145
+ border-bottom-color: var(--border-hover);
146
+ box-shadow: 0 var(--size-2) var(--size-10) color-mix(in srgb, var(--brand) 5%, transparent);
147
+ }
148
+
149
+ .header-inner {
150
+ max-width: none;
151
+ margin: 0 auto;
152
+ padding: 0 clamp(var(--size-5), 3.5vw, var(--size-9));
153
+ display: flex;
154
+ align-items: center;
155
+ min-height: var(--nav-height);
156
+ gap: var(--size-6);
157
+ }
158
+
159
+ .mobile-tab-bar { display: none; }
160
+
161
+ .mobile-menu-btn {
162
+ display: none;
163
+ align-items: center;
164
+ justify-content: center;
165
+ width: var(--size-10);
166
+ height: var(--size-10);
167
+ border: var(--border-size-1) solid var(--border);
168
+ border-radius: var(--radius-round);
169
+ background: color-mix(in srgb, var(--bg-elevated) 74%, transparent);
170
+ color: var(--text-secondary);
171
+ cursor: pointer;
172
+ padding: 0;
173
+ transition: all 0.15s ease;
174
+ }
175
+ .mobile-menu-btn:hover {
176
+ color: var(--text-primary);
177
+ border-color: var(--border-hover);
178
+ background: var(--bg-hover);
179
+ }
180
+
181
+ .logo {
182
+ display: inline-flex;
183
+ align-items: center;
184
+ gap: var(--size-3);
185
+ font-size: var(--font-size-3);
186
+ font-weight: var(--font-weight-8);
187
+ color: var(--text-primary);
188
+ text-decoration: none;
189
+ letter-spacing: 0;
190
+ white-space: nowrap;
191
+ }
192
+
193
+ .logo:hover open-brand-mark {
194
+ transform: translateY(calc(var(--border-size-1) * -1));
195
+ }
196
+
197
+ open-brand-mark {
198
+ transition: transform var(--duration-2) var(--ease-2);
199
+ }
200
+
201
+ .logo-word {
202
+ display: inline-block;
203
+ transform: translateY(calc(var(--border-size-1) * -1));
204
+ }
205
+
206
+ .logo-sub {
207
+ font-size: var(--font-size-00);
208
+ color: var(--text-muted);
209
+ margin-left: var(--size-2);
210
+ font-family: var(--font-mono);
211
+ font-weight: var(--font-weight-8);
212
+ text-transform: uppercase;
213
+ }
214
+
215
+ .header-nav {
216
+ display: flex;
217
+ gap: clamp(var(--size-5), 3vw, var(--size-8));
218
+ flex: 1;
219
+ justify-content: center;
220
+ }
221
+ .header-nav a {
222
+ color: var(--nav-link-color);
223
+ text-decoration: none;
224
+ font-size: var(--font-size-1);
225
+ font-weight: var(--font-weight-5);
226
+ padding: var(--size-2) 0;
227
+ transition: color 0.15s ease, background 0.15s ease;
228
+ }
229
+ .header-nav a:hover {
230
+ color: var(--nav-link-hover);
231
+ }
232
+ .header-nav a[aria-current="page"] {
233
+ color: var(--brand-deep);
234
+ font-weight: var(--font-weight-8);
235
+ }
236
+
237
+ .header-right {
238
+ display: flex;
239
+ align-items: center;
240
+ gap: var(--size-1);
241
+ margin-left: auto;
242
+ }
243
+
244
+ /* CTA buttons */
245
+ .btn-secondary {
246
+ display: inline-flex;
247
+ align-items: center;
248
+ gap: var(--size-2);
249
+ color: var(--text-primary);
250
+ text-decoration: none;
251
+ font-size: var(--font-size-button);
252
+ font-weight: var(--font-weight-semibold);
253
+ padding: var(--size-2) var(--size-4);
254
+ border: var(--border-size-1) solid color-mix(in srgb, var(--border) 72%, var(--brand));
255
+ border-radius: var(--radius-round);
256
+ background: color-mix(in srgb, var(--bg-elevated) 76%, transparent);
257
+ box-shadow: inset 0 1px 0 color-mix(in srgb, var(--gray-0) 70%, transparent);
258
+ transition: all 0.15s ease;
259
+ }
260
+ .btn-secondary:hover {
261
+ color: var(--brand-deep);
262
+ border-color: var(--brand-light);
263
+ background: color-mix(in srgb, var(--brand-pale) 42%, var(--bg-elevated));
264
+ }
265
+ .btn-secondary svg { flex-shrink: 0; }
266
+
267
+ .btn-primary {
268
+ display: inline-flex;
269
+ align-items: center;
270
+ gap: 4px;
271
+ color: var(--on-brand);
272
+ text-decoration: none;
273
+ font-size: var(--font-size-button);
274
+ font-weight: var(--font-weight-semibold);
275
+ padding: var(--size-2) var(--size-4);
276
+ border: var(--border-size-1) solid transparent;
277
+ border-radius: var(--radius-round);
278
+ background: linear-gradient(135deg, var(--brand), var(--brand-light));
279
+ box-shadow: 0 var(--size-2) var(--size-5) var(--brand-glow);
280
+ white-space: nowrap;
281
+ transition: all 0.15s ease;
282
+ }
283
+ .btn-primary:hover {
284
+ background: linear-gradient(135deg, var(--brand-hover), var(--brand-light));
285
+ transform: translateY(calc(var(--border-size-1) * -1));
286
+ }
287
+
288
+ .header-right .btn-secondary,
289
+ .header-right .btn-primary {
290
+ display: none;
291
+ }
292
+
293
+ .lang-switch {
294
+ display: inline-flex;
295
+ align-items: center;
296
+ justify-content: center;
297
+ min-width: var(--size-9);
298
+ width: var(--size-9);
299
+ height: var(--size-9);
300
+ padding: 0;
301
+ font-size: var(--font-size-button);
302
+ font-weight: var(--font-weight-semibold);
303
+ color: var(--text-secondary);
304
+ border: 0;
305
+ border-radius: var(--radius-round);
306
+ background: transparent;
307
+ cursor: pointer;
308
+ text-decoration: none;
309
+ transition: all 0.15s ease;
310
+ }
311
+ .lang-switch:hover {
312
+ color: var(--brand-deep);
313
+ border-color: transparent;
314
+ background: color-mix(in srgb, var(--brand-pale) 34%, transparent);
315
+ }
316
+
317
+ /* Sidebar */
318
+ .docs-sidebar {
319
+ width: clamp(200px, 20vw, 260px);
320
+ flex-shrink: 0;
321
+ border-right: var(--border-size-1) solid var(--border);
322
+ padding: 2rem 0;
323
+ overflow-y: auto;
324
+ height: calc(100vh - var(--nav-height));
325
+ position: sticky;
326
+ top: var(--nav-height);
327
+ scrollbar-width: thin;
328
+ background: color-mix(in srgb, var(--bg-elevated) 42%, transparent);
329
+ }
330
+ :host([home]) .docs-sidebar,
331
+ :host([full-width]) .docs-sidebar {
332
+ width: 0; min-width: 0; padding: 0;
333
+ overflow: hidden; border-right: none;
334
+ }
335
+
336
+ .nav-section { margin-bottom: 1.5rem; }
337
+ .nav-section summary {
338
+ font-size: 0.625rem;
339
+ font-weight: 800;
340
+ text-transform: uppercase;
341
+ letter-spacing: 0.22em;
342
+ color: var(--text-muted);
343
+ padding: 0 1.5rem;
344
+ margin-bottom: 0.5rem;
345
+ cursor: pointer;
346
+ list-style: none;
347
+ display: flex;
348
+ align-items: center;
349
+ gap: 0.5rem;
350
+ user-select: none;
351
+ }
352
+ .nav-section summary::-webkit-details-marker { display: none; }
353
+ .nav-section summary::marker { content: ""; }
354
+ .nav-section summary:hover { color: var(--text-secondary); }
355
+
356
+ .docs-sidebar a {
357
+ display: block;
358
+ color: var(--text-muted);
359
+ text-decoration: none;
360
+ font-size: 0.85rem;
361
+ padding: 0.35rem 1.5rem;
362
+ border-left: 2px solid transparent;
363
+ transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
364
+ }
365
+ .docs-sidebar a:hover {
366
+ color: var(--text-secondary);
367
+ background: var(--bg-hover);
368
+ }
369
+ .docs-sidebar a.active,
370
+ .docs-sidebar a[aria-current="page"] {
371
+ color: var(--brand);
372
+ border-left-color: var(--brand);
373
+ background: var(--brand-subtle);
374
+ font-weight: 600;
375
+ }
376
+
377
+ /* Footer */
378
+ .app-footer {
379
+ border-top: var(--border-size-1) solid var(--border);
380
+ background: color-mix(in srgb, var(--bg-elevated) 58%, transparent);
381
+ }
382
+ .footer-inner {
383
+ max-width: 1240px;
384
+ margin: 0 auto;
385
+ padding: var(--size-16) var(--size-8);
386
+ display: grid;
387
+ grid-template-columns: repeat(4, 1fr);
388
+ gap: var(--size-8);
389
+ }
390
+ .footer-column h4 {
391
+ font-size: var(--font-size-button);
392
+ font-weight: var(--font-weight-semibold);
393
+ color: var(--text-primary);
394
+ margin: 0 0 var(--size-4);
395
+ }
396
+ .footer-column a {
397
+ display: block;
398
+ color: var(--text-secondary);
399
+ text-decoration: none;
400
+ font-size: var(--font-size-body-sm);
401
+ padding: 4px 0;
402
+ transition: color 0.15s ease;
403
+ }
404
+ .footer-column a:hover {
405
+ color: var(--text-primary);
406
+ }
407
+ .footer-bottom {
408
+ border-top: var(--border-size-1) solid var(--border);
409
+ padding: var(--size-4) var(--size-8);
410
+ max-width: 1240px;
411
+ margin: 0 auto;
412
+ display: flex;
413
+ justify-content: space-between;
414
+ align-items: center;
415
+ color: var(--text-muted);
416
+ font-size: var(--font-size-body-sm);
417
+ }
418
+ .footer-bottom a {
419
+ color: var(--text-secondary);
420
+ text-decoration: none;
421
+ transition: color 0.15s ease;
422
+ }
423
+ .footer-bottom a:hover {
424
+ color: var(--text-primary);
425
+ }
426
+
427
+ /* Mobile backdrop */
428
+ .mobile-backdrop {
429
+ position: fixed; inset: 0; top: var(--nav-height);
430
+ background: var(--overlay);
431
+ z-index: 80; opacity: 0; pointer-events: none;
432
+ transition: opacity 0.3s ease;
433
+ }
434
+
435
+ /* Responsive */
436
+ @media (max-width: 1120px) {
437
+ .header-inner {
438
+ gap: var(--size-3);
439
+ padding-inline: var(--size-4);
440
+ }
441
+
442
+ .header-nav {
443
+ gap: var(--size-3);
444
+ }
445
+
446
+ .btn-secondary .btn-text { display: none; }
447
+ }
448
+
449
+ @media (max-width: 900px) {
450
+ .mobile-menu-btn { display: flex; }
451
+ .header-inner { padding: 0 var(--size-4); gap: var(--size-2); }
452
+ .header-nav { display: none; }
453
+ .btn-secondary .btn-text { display: none; }
454
+ .header-right { gap: 4px; }
455
+
456
+ .docs-sidebar {
457
+ position: fixed; top: var(--nav-height); left: 0;
458
+ width: min(280px, 80vw);
459
+ height: calc(100vh - var(--nav-height)); z-index: 90;
460
+ background: var(--bg-elevated);
461
+ border-right: var(--border-size-1) solid var(--border);
462
+ padding: 1rem 0; overflow-y: auto;
463
+ transform: translateX(-101%);
464
+ transition: transform 0.25s cubic-bezier(0.4,0,0.2,1);
465
+ will-change: transform;
466
+ }
467
+ :host([menu-open]) .docs-sidebar {
468
+ transform: translateX(0);
469
+ box-shadow: var(--shadow-1);
470
+ }
471
+ :host([menu-open]) .mobile-backdrop { opacity: 1; pointer-events: auto; }
472
+ .nav-section { margin-bottom: 0.5rem; }
473
+ .nav-section summary { padding: var(--size-2) var(--size-4); }
474
+ .docs-sidebar a { padding: 0.5rem 1rem 0.5rem 2rem; }
475
+ .layout-main { width: 100%; }
476
+ .app-footer { padding: 0; }
477
+ .footer-inner {
478
+ grid-template-columns: repeat(2, 1fr);
479
+ padding: var(--size-12) var(--size-4);
480
+ padding-bottom: calc(var(--size-12) + var(--size-16));
481
+ }
482
+ .footer-bottom {
483
+ flex-direction: column;
484
+ gap: var(--size-2);
485
+ padding: var(--size-4);
486
+ padding-bottom: calc(var(--size-4) + var(--size-16));
487
+ text-align: center;
488
+ }
489
+
490
+ .mobile-tab-bar {
491
+ display: flex; position: fixed; bottom: 0; left: 0; right: 0;
492
+ height: 56px; z-index: 100;
493
+ background: var(--nav-bg);
494
+ backdrop-filter: blur(12px) saturate(180%);
495
+ -webkit-backdrop-filter: blur(12px) saturate(180%);
496
+ border-top: var(--border-size-1) solid var(--border);
497
+ padding: 0 env(safe-area-inset-right) 0 env(safe-area-inset-left);
498
+ padding-bottom: env(safe-area-inset-bottom);
499
+ }
500
+ .tab-item {
501
+ flex: 1; display: flex; flex-direction: column;
502
+ align-items: center; justify-content: center; gap: 2px;
503
+ color: var(--text-muted);
504
+ text-decoration: none; font-size: 10px; font-weight: 600;
505
+ transition: color 0.15s ease;
506
+ -webkit-tap-highlight-color: transparent; padding: 4px 0;
507
+ }
508
+ .tab-item svg { width: 20px; height: 20px; flex-shrink: 0; }
509
+ .tab-item:hover { color: var(--text-secondary); }
510
+ .tab-item.active { color: var(--brand); }
511
+ }
512
+
513
+ @media (max-width: 768px) {
514
+ .header-right { gap: 4px; }
515
+ .lang-switch { display: none; }
516
+ }
517
+ @media (max-width: 480px) {
518
+ .btn-primary { display: none; }
519
+ .btn-secondary { padding: 8px; border: none; }
520
+ .btn-secondary .btn-text { display: none; }
521
+ .header-inner { padding: 0 var(--size-3); gap: var(--size-1); }
522
+ }
523
+ `);
524
+ export class OpenLayout extends OpenElement {
525
+ _cleanupNav;
526
+ _scrollCleanup;
527
+ _navOptions;
528
+ get _locales() {
529
+ try {
530
+ const raw = this.locales || this.getAttribute('locales');
531
+ if (raw) {
532
+ if (Array.isArray(raw)) return raw;
533
+ if (typeof raw === 'string') {
534
+ try {
535
+ return JSON.parse(raw);
536
+ } catch {}
537
+ }
538
+ }
539
+ return [
540
+ 'en'
541
+ ];
542
+ } catch {
543
+ return [
544
+ 'en'
545
+ ];
546
+ }
547
+ }
548
+ get _defaultLocale() {
549
+ return this.getAttribute('locale') || this._locales[0] || 'en';
550
+ }
551
+ get _currentLocale() {
552
+ try {
553
+ if (typeof globalThis.location !== 'undefined') {
554
+ return detectLocale(location.pathname, this._locales, this._defaultLocale);
555
+ }
556
+ return this._defaultLocale;
557
+ } catch {
558
+ return this._defaultLocale;
559
+ }
560
+ }
561
+ get _currentPathWithoutLocale() {
562
+ try {
563
+ if (typeof globalThis.location !== 'undefined') {
564
+ return parsePathWithoutLocale(location.pathname, this._locales);
565
+ }
566
+ return this.getAttribute('current-path') || '/';
567
+ } catch {
568
+ return '/';
569
+ }
570
+ }
571
+ static styles = [
572
+ sheet
573
+ ];
574
+ static observedAttributes = [
575
+ 'current-path',
576
+ 'nav-items',
577
+ 'header-nav',
578
+ 'logo-text',
579
+ 'logo-sub',
580
+ 'github-url',
581
+ 'edit-url',
582
+ 'locale',
583
+ 'locales'
584
+ ];
585
+ _themeHandler;
586
+ _docClickCleanup;
587
+ render() {
588
+ return this._renderLayout();
589
+ }
590
+ _getStr(attr, def) {
591
+ const camel = attr.replace(/-([a-z])/g, (_, c)=>c.toUpperCase());
592
+ const prop = this[camel];
593
+ if (prop !== undefined && prop !== null) return String(prop);
594
+ return this.getAttribute(attr) || def;
595
+ }
596
+ _getBool(attr) {
597
+ const camel = attr.replace(/-([a-z])/g, (_, c)=>c.toUpperCase());
598
+ const prop = this[camel];
599
+ if (typeof prop === 'boolean') return prop;
600
+ return this.hasAttribute(attr);
601
+ }
602
+ // _currentPathWithoutLocale, _currentLocale, _locales, _switchPath(),
603
+ // _switchLabel(), _updateSwitch(), _localizePath()
604
+ // ?? all inlined (replaces former @openelement/router dependency)
605
+ _currentPath() {
606
+ // SSR-safe: prefer attribute/prop set by renderDsd over URL detection
607
+ // location.pathname is undefined during build.
608
+ const prop = this.currentPath;
609
+ if (typeof prop === 'string' && prop.length > 0) return prop;
610
+ const attr = this.getAttribute('current-path');
611
+ if (attr && attr.length > 0) return attr;
612
+ try {
613
+ if (typeof globalThis.location !== 'undefined') {
614
+ return parsePathWithoutLocale(location.pathname, this._locales);
615
+ }
616
+ return this.getAttribute('current-path') || '/';
617
+ } catch {
618
+ return '/';
619
+ }
620
+ }
621
+ /** Compute GitHub edit URL from current path. */ _computeEditUrl() {
622
+ const path1 = this._currentPath();
623
+ if (!path1 || path1 === '/') return '';
624
+ const EDIT_BASE = 'https://github.com/open-element/openelement/edit/main/www/app/routes';
625
+ const clean = path1.replace(/\/$/, '').split('/').filter(Boolean);
626
+ // Remove locale prefix if present (en/, zh/)
627
+ if ([
628
+ 'en',
629
+ 'zh'
630
+ ].includes(clean[0])) clean.shift();
631
+ const filePath = clean.length === 0 ? 'index/index' : clean.join('/');
632
+ return `${EDIT_BASE}/${filePath}.tsx`;
633
+ }
634
+ _navItems() {
635
+ const items = this._rawNavItems();
636
+ return this._filterByPath(items);
637
+ }
638
+ /** Auto-filter sidebar sections by current path prefix. */ _filterByPath(items) {
639
+ const path1 = this._currentPath();
640
+ const SECTION_MAP = {
641
+ '/guide': [
642
+ 'Quick Start',
643
+ 'Core',
644
+ 'Production'
645
+ ],
646
+ '/architecture': [
647
+ 'Principles',
648
+ 'Compatibility',
649
+ 'Reference'
650
+ ],
651
+ '/registry': [
652
+ 'Registry'
653
+ ],
654
+ '/hub': [
655
+ 'Registry'
656
+ ],
657
+ '/blog': [
658
+ 'History'
659
+ ]
660
+ };
661
+ for (const [prefix, sections] of Object.entries(SECTION_MAP)){
662
+ if (path1.startsWith(prefix)) {
663
+ return items.filter((s)=>sections.includes(s.section));
664
+ }
665
+ }
666
+ return items;
667
+ }
668
+ _rawNavItems() {
669
+ try {
670
+ const prop = this.navItems;
671
+ if (prop && Array.isArray(prop)) return prop;
672
+ const raw = this.getAttribute('nav-items');
673
+ if (raw) return JSON.parse(raw);
674
+ return [];
675
+ } catch (e) {
676
+ log.warn('Failed to parse nav-items JSON:', e);
677
+ return [];
678
+ }
679
+ }
680
+ _headerNav() {
681
+ try {
682
+ const prop = this.headerNav;
683
+ if (prop && Array.isArray(prop)) return prop;
684
+ const raw = this.getAttribute('header-nav');
685
+ if (raw) return JSON.parse(raw);
686
+ return [];
687
+ } catch (e) {
688
+ log.warn('Failed to parse header-nav JSON:', e);
689
+ return [];
690
+ }
691
+ }
692
+ // --- Icons ---
693
+ /** v0.24.1: SVG icon attributes shared across all mobile tab bar icons. */ static _ICON_ATTRS = {
694
+ viewBox: '0 0 20 20',
695
+ fill: 'none',
696
+ stroke: 'currentColor',
697
+ 'stroke-width': '1.5',
698
+ 'stroke-linecap': 'round',
699
+ 'stroke-linejoin': 'round'
700
+ };
701
+ /** v0.24.1: Render mobile tab icon as JSX SVG. Falls back to a generic shape. */ _renderIcon(label) {
702
+ const a1 = OpenLayout._ICON_ATTRS;
703
+ switch(label){
704
+ case 'Home':
705
+ return <svg {...a1}>
706
+ <path d='M3 10l7-7 7 7'/>
707
+ <path d='M5 8v9h3v-5h4v5h3V8'/>
708
+ </svg>;
709
+ case 'Docs':
710
+ case 'Blog':
711
+ return <svg {...a1}>
712
+ <rect x='3' y='2' width='14' height='16' rx='2'/>
713
+ <path d='M7 6h6M7 10h6M7 14h3'/>
714
+ </svg>;
715
+ case 'Examples':
716
+ return <svg {...a1}>
717
+ <rect x='3' y='3' width='14' height='14' rx='2'/>
718
+ <path d='M7 7l6 3-6 3z'/>
719
+ </svg>;
720
+ case 'Components':
721
+ return <svg {...a1}>
722
+ <rect x='2' y='2' width='7' height='7' rx='1'/>
723
+ <rect x='11' y='2' width='7' height='7' rx='1'/>
724
+ <rect x='2' y='11' width='7' height='7' rx='1'/>
725
+ <rect x='11' y='11' width='7' height='7' rx='1'/>
726
+ </svg>;
727
+ case 'Architecture':
728
+ case 'Engine':
729
+ return <svg {...a1}>
730
+ <circle cx='10' cy='10' r='3'/>
731
+ <path d='M10 1v2M10 17v2M3.5 3.5l1.4 1.4M15.1 15.1l1.4 1.4M1 10h2M17 10h2M3.5 16.5l1.4-1.4M15.1 4.9l1.4-1.4'/>
732
+ </svg>;
733
+ case 'Hub':
734
+ case 'RegistryHub':
735
+ return <svg {...a1}>
736
+ <path d='M10 2l7 4v8l-7 4-7-4V6z'/>
737
+ <path d='M10 10l7-4M10 10v8M10 10L3 6'/>
738
+ </svg>;
739
+ case 'Roadmap':
740
+ return <svg {...a1}>
741
+ <circle cx='4' cy='6' r='1.5'/>
742
+ <circle cx='10' cy='10' r='1.5'/>
743
+ <circle cx='16' cy='14' r='1.5'/>
744
+ <path d='M5.5 6h10M11.5 10h5'/>
745
+ </svg>;
746
+ case 'Framework':
747
+ return <svg {...a1}>
748
+ <path d='M5 3h10M5 3v6h7M12 9v3M5 17h7'/>
749
+ </svg>;
750
+ default:
751
+ return <svg {...a1}>
752
+ <circle cx='10' cy='10' r='8'/>
753
+ <path d='M6 6l3 5 5 3-3-5z'/>
754
+ </svg>;
755
+ }
756
+ }
757
+ _safeHref(href, fallback = '#') {
758
+ if (!href) return fallback;
759
+ const trimmed = href.trim();
760
+ return isSafeLayoutUrl(trimmed) ? trimmed : fallback;
761
+ }
762
+ _isExternalHref(href) {
763
+ try {
764
+ const parsed = new URL(href, 'https://openelement.org/');
765
+ return parsed.origin !== 'https://openelement.org' && SAFE_URL_SCHEMES.has(parsed.protocol);
766
+ } catch {
767
+ return false;
768
+ }
769
+ }
770
+ _localizedSafeHref(href) {
771
+ const safeHref = this._safeHref(href);
772
+ const isExternal = this._isExternalHref(safeHref);
773
+ return {
774
+ href: isExternal ? safeHref : localizePath(safeHref, this._currentLocale),
775
+ isExternal
776
+ };
777
+ }
778
+ // --- Main render ---
779
+ _renderLayout() {
780
+ const home = this._getBool('full-width') || this._getBool('home');
781
+ const noSearch = this.hasAttribute('no-search');
782
+ const logoText = this._getStr('logo-text', '');
783
+ const logoSub = this._getStr('logo-sub', '');
784
+ const locales = this._locales;
785
+ const currentLocale = this._currentLocale;
786
+ const currentPath = this._currentPathWithoutLocale;
787
+ const langLabel = locales.length > 1 ? switchLabel(currentLocale) : '';
788
+ const langHref = locales.length > 1 ? switchPath(currentPath, currentLocale, locales) : '';
789
+ return <div className='app-layout' part='container' home={home || undefined}>
790
+ <header className='app-header' part='header'>
791
+ <nav className='header-inner' aria-label='Primary navigation'>
792
+ {(logoText || logoSub) && <a className='logo' href='/'>
793
+ <open-brand-mark size='md'></open-brand-mark>
794
+ {logoText && <span className='logo-word'>{logoText}</span>}
795
+ {logoSub && <span className='logo-sub'>{logoSub}</span>}
796
+ </a>}
797
+ {this._renderHeaderNav()}
798
+ <div className='header-right'>
799
+ {!noSearch && <open-search></open-search>}
800
+ {!home && <button type='button' className='mobile-menu-btn' part='nav-toggle' aria-label='Toggle navigation' onClick={(event)=>this._toggleMenu(event)}>
801
+ <svg width='18' height='18' viewBox='0 0 18 18' fill='none' stroke='currentColor' stroke-width='1.5' stroke-linecap='round'>
802
+ <line x1='3' y1='4.5' x2='15' y2='4.5'/>
803
+ <line x1='3' y1='9' x2='15' y2='9'/>
804
+ <line x1='3' y1='13.5' x2='15' y2='13.5'/>
805
+ </svg>
806
+ </button>}
807
+ <open-theme-toggle></open-theme-toggle>
808
+ {locales.length > 1 && <a className='lang-switch' href={langHref} data-nav={langHref}>
809
+ {langLabel}
810
+ </a>}
811
+ </div>
812
+ </nav>
813
+ </header>
814
+ <div className='mobile-backdrop'></div>
815
+ <div className='layout-body'>
816
+ {!home && this._renderSidebarNav()}
817
+ <main className='layout-main' part='main'>
818
+ <slot></slot>
819
+ </main>
820
+ </div>
821
+ <footer className='app-footer' part='footer'>
822
+ <div className='footer-inner'>
823
+ <div className='footer-column'>
824
+ <h4>Product</h4>
825
+ <a href={localizePath('/guide/core-concepts', currentLocale)} data-nav={localizePath('/guide/core-concepts', currentLocale)}>
826
+ Elements
827
+ </a>
828
+ <a href={localizePath('/architecture/design-system', currentLocale)} data-nav={localizePath('/architecture/design-system', currentLocale)}>
829
+ UI
830
+ </a>
831
+ <a href={localizePath('/architecture/architecture', currentLocale)} data-nav={localizePath('/architecture/architecture', currentLocale)}>
832
+ Framework
833
+ </a>
834
+ <a href={localizePath('/architecture/standards-registry', currentLocale)} data-nav={localizePath('/architecture/standards-registry', currentLocale)}>
835
+ Protocols
836
+ </a>
837
+ </div>
838
+ <div className='footer-column'>
839
+ <h4>Resources</h4>
840
+ <a href={localizePath('/guide/getting-started', currentLocale)} data-nav={localizePath('/guide/getting-started', currentLocale)}>
841
+ Guide
842
+ </a>
843
+ <a href={localizePath('/guide/api', currentLocale)} data-nav={localizePath('/guide/api', currentLocale)}>
844
+ API
845
+ </a>
846
+ <a href={localizePath('/architecture/architecture', currentLocale)} data-nav={localizePath('/architecture/architecture', currentLocale)}>
847
+ Architecture
848
+ </a>
849
+ <a href={localizePath('/blog', currentLocale)} data-nav={localizePath('/blog', currentLocale)}>
850
+ Blog
851
+ </a>
852
+ </div>
853
+ <div className='footer-column'>
854
+ <h4>Company</h4>
855
+ <a href='https://github.com/open-element/openelement'>GitHub</a>
856
+ <a href={localizePath('/roadmap', currentLocale)} data-nav={localizePath('/roadmap', currentLocale)}>
857
+ Roadmap
858
+ </a>
859
+ <a href={localizePath('/changelog', currentLocale)} data-nav={localizePath('/changelog', currentLocale)}>
860
+ Changelog
861
+ </a>
862
+ </div>
863
+ <div className='footer-column'>
864
+ <h4>Legal</h4>
865
+ <a href='https://github.com/open-element/openelement/blob/main/LICENSE'>
866
+ MIT License
867
+ </a>
868
+ <a href={localizePath('/contributing', currentLocale)} data-nav={localizePath('/contributing', currentLocale)}>
869
+ Contributing
870
+ </a>
871
+ </div>
872
+ </div>
873
+ <div className='footer-bottom'>
874
+ <span>(c) 2026 openElement. MIT License.</span>
875
+ </div>
876
+ </footer>
877
+ {this._renderMobileTabBar()}
878
+ </div>;
879
+ }
880
+ _renderHeaderNav() {
881
+ const links = this._headerNav();
882
+ if (links.length === 0) return null;
883
+ const cp = this._currentPath();
884
+ return <nav className='header-nav' part='nav'>
885
+ {links.map((link)=>{
886
+ const { href: localized, isExternal } = this._localizedSafeHref(link.href);
887
+ const isCurrent = !isExternal && (cp === link.href || cp === localized || cp.startsWith(localized + '/'));
888
+ return <a href={localized} data-nav={isExternal ? '' : localized} aria-current={isCurrent ? 'page' : undefined}>
889
+ {link.label}
890
+ </a>;
891
+ })}
892
+ </nav>;
893
+ }
894
+ _renderSidebarNav() {
895
+ const nav1 = this._navItems();
896
+ if (nav1.length === 0) return null;
897
+ return <nav className='docs-sidebar' part='sidebar' aria-label='Documentation navigation'>
898
+ {nav1.map((section)=><details className='nav-section' open>
899
+ <summary className='nav-section-title'>
900
+ {section.section}
901
+ </summary>
902
+ {section.items.map((item)=>{
903
+ const href = item.href || item.path || '#';
904
+ const { href: localized, isExternal } = this._localizedSafeHref(href);
905
+ const cp = this._currentPath();
906
+ const isActive = !isExternal && cp === localized;
907
+ return <a href={localized} className={isActive ? 'active' : undefined} aria-current={isActive ? 'page' : undefined} data-nav={isExternal ? '' : localized}>
908
+ {item.label}
909
+ </a>;
910
+ })}
911
+ </details>)}
912
+ </nav>;
913
+ }
914
+ _renderMobileTabBar() {
915
+ const links = this._headerNav();
916
+ if (links.length === 0) return null;
917
+ const MOBILE_TAB_LIMIT = 5;
918
+ const mobileLinks = links.slice(0, MOBILE_TAB_LIMIT);
919
+ const locs = this._locales;
920
+ const sectionRoot = (href)=>{
921
+ const segs = href.split('/').filter(Boolean);
922
+ const start = locs.length > 1 && locs.includes(segs[0]) ? 1 : 0;
923
+ return segs.length > start + 1 ? '/' + segs[start] : href;
924
+ };
925
+ const rawPath = this._currentPathWithoutLocale;
926
+ return <nav className='mobile-tab-bar' aria-label='Quick navigation'>
927
+ {mobileLinks.map((link)=>{
928
+ const { href: localized, isExternal } = this._localizedSafeHref(link.href);
929
+ const root = sectionRoot(link.href);
930
+ const isActive = !isExternal && (rawPath === root || rawPath.startsWith(root + '/'));
931
+ return <a className={`tab-item${isActive ? ' active' : ''}`} href={localized} data-nav={isExternal ? '' : localized} aria-current={isActive ? 'page' : undefined}>
932
+ {this._renderIcon(link.label)}
933
+ <span>{link.label}</span>
934
+ </a>;
935
+ })}
936
+ </nav>;
937
+ }
938
+ // --- Scroll detection ---
939
+ _setupScrollDetection() {
940
+ if (typeof globalThis.window === 'undefined') return;
941
+ let ticking;
942
+ const onScroll = ()=>{
943
+ if (ticking !== undefined) return;
944
+ ticking = globalThis.setTimeout(()=>{
945
+ const header1 = this.shadowRoot?.querySelector('.app-header');
946
+ if (header1) {
947
+ header1.classList.toggle('scrolled', globalThis.scrollY > 0);
948
+ }
949
+ ticking = undefined;
950
+ }, 100);
951
+ };
952
+ globalThis.addEventListener('scroll', onScroll, {
953
+ passive: true
954
+ });
955
+ this._scrollCleanup = ()=>{
956
+ globalThis.removeEventListener('scroll', onScroll);
957
+ if (ticking !== undefined) {
958
+ globalThis.clearTimeout(ticking);
959
+ }
960
+ };
961
+ }
962
+ _teardownScrollDetection() {
963
+ this._scrollCleanup?.();
964
+ this._scrollCleanup = undefined;
965
+ }
966
+ // --- Lifecycle ---
967
+ connectedCallback() {
968
+ super.connectedCallback();
969
+ const locales = this._locales;
970
+ if (locales.length > 1) {
971
+ const locale = this._currentLocale;
972
+ if (locales.includes(locale)) {
973
+ this.setAttribute('locale', locale);
974
+ }
975
+ }
976
+ // Sync data-theme from document.documentElement on connect
977
+ const docTheme = document.documentElement?.dataset?.theme;
978
+ if (docTheme) {
979
+ this.setAttribute('data-theme', docTheme);
980
+ }
981
+ // SignalContext: provide theme state to all child components
982
+ const initialTheme = docTheme || 'light';
983
+ provideContext(this, THEME_CTX, initialTheme);
984
+ // Listen for theme change events from open-theme-toggle
985
+ this._themeHandler = (e)=>{
986
+ const detail = e.detail;
987
+ if (detail?.theme) {
988
+ this.setAttribute('data-theme', detail.theme);
989
+ provideContext(this, THEME_CTX, detail.theme);
990
+ this._propagateTheme(detail.theme);
991
+ }
992
+ };
993
+ globalThis.addEventListener?.('open:theme-change', this._themeHandler);
994
+ this._propagateTheme(initialTheme);
995
+ if (this.shadowRoot && this.shadowRoot.childNodes.length > 0) {
996
+ this._setupDetailsToggle();
997
+ }
998
+ this._setupSpaNavigation({
999
+ contentLoader: async (path1, locale)=>{
1000
+ await this._loadContent(path1, locale);
1001
+ },
1002
+ onAfterSwap: (_path)=>{
1003
+ this._updateActiveNav();
1004
+ }
1005
+ });
1006
+ // v0.23.0: Integrated from www/public/mobile-menu.js.
1007
+ // Close mobile menu on backdrop click or sidebar nav link click.
1008
+ this._docClickCleanup = this._setupBackdropClose();
1009
+ // Scroll detection for header backdrop blur
1010
+ this._setupScrollDetection();
1011
+ }
1012
+ disconnectedCallback() {
1013
+ super.disconnectedCallback();
1014
+ this._teardownSpaNavigation();
1015
+ this._docClickCleanup?.();
1016
+ if (this._themeHandler) {
1017
+ globalThis.removeEventListener?.('open:theme-change', this._themeHandler);
1018
+ }
1019
+ this._teardownScrollDetection();
1020
+ }
1021
+ attributeChangedCallback(name, old, val) {
1022
+ if (old === val) return;
1023
+ if (name === 'current-path') {
1024
+ this._updateActiveNav();
1025
+ }
1026
+ }
1027
+ // --- Mobile menu ---
1028
+ // v0.31 UI-shell debt: replace _replaceShadowRootFromLayout with signal-driven SPA nav.
1029
+ // Currently SPA navigation destroys the entire shadow DOM and rebuilds it from
1030
+ // fetched HTML, then manually re-attaches events in _setupDetailsToggle. This is
1031
+ // incompatible with the signal architecture ?? we should make currentPath/navItems
1032
+ // signals and let data-signal markers handle DOM updates reactively. Then the
1033
+ // _setupDetailsToggle hack (and this entire method) can be deleted.
1034
+ _menuBtnHandler = null;
1035
+ _setupDetailsToggle() {
1036
+ const btn = this.shadowRoot?.querySelector('.mobile-menu-btn');
1037
+ if (!btn) return;
1038
+ // Remove any stale listener from a previous shadow root.
1039
+ if (this._menuBtnHandler) {
1040
+ btn.removeEventListener('click', this._menuBtnHandler);
1041
+ }
1042
+ this._menuBtnHandler = this._toggleMenu.bind(this);
1043
+ btn.addEventListener('click', this._menuBtnHandler);
1044
+ }
1045
+ _toggleMenu(_e) {
1046
+ const isOpen = this.hasAttribute('menu-open');
1047
+ this.toggleAttribute('menu-open', !isOpen);
1048
+ this._syncInert(!isOpen);
1049
+ }
1050
+ _syncInert(menuOpen) {
1051
+ const main1 = this.shadowRoot?.querySelector('.layout-main');
1052
+ if (main1) {
1053
+ if (menuOpen) main1.setAttribute('inert', '');
1054
+ else main1.removeAttribute('inert');
1055
+ }
1056
+ }
1057
+ /**
1058
+ * v0.23.0: Integrated from www/public/mobile-menu.js.
1059
+ * Closes mobile menu when backdrop or sidebar nav link is clicked.
1060
+ * Uses composedPath() to detect clicks across shadow DOM boundaries.
1061
+ */ _setupBackdropClose() {
1062
+ const handler = (e)=>{
1063
+ const target = e.target;
1064
+ if (!target || !(target instanceof Element)) return;
1065
+ const path1 = e.composedPath();
1066
+ let isBackdrop = false;
1067
+ let isNavLink = false;
1068
+ for(let i = 0; i < path1.length; i++){
1069
+ const el = path1[i];
1070
+ if (!el?.classList) continue;
1071
+ if (el.classList.contains('mobile-backdrop')) {
1072
+ isBackdrop = true;
1073
+ break;
1074
+ }
1075
+ if (el.tagName === 'A') {
1076
+ isNavLink = true;
1077
+ break;
1078
+ }
1079
+ }
1080
+ if (!isBackdrop && !isNavLink) return;
1081
+ this._closeMenu();
1082
+ };
1083
+ document.addEventListener('click', handler);
1084
+ return ()=>document.removeEventListener('click', handler);
1085
+ }
1086
+ _closeMenu() {
1087
+ this.removeAttribute('menu-open');
1088
+ const details1 = this.shadowRoot?.querySelector('details.mobile-menu');
1089
+ if (details1) details1.removeAttribute('open');
1090
+ this._syncInert(false);
1091
+ }
1092
+ // --- Theme ---
1093
+ _propagateTheme(theme) {
1094
+ const walk = (root)=>{
1095
+ root.querySelectorAll('*').forEach((el)=>{
1096
+ if (el.tagName.includes('-')) {
1097
+ el.setAttribute('data-theme', theme);
1098
+ }
1099
+ if (el.shadowRoot) {
1100
+ walk(el.shadowRoot);
1101
+ }
1102
+ });
1103
+ };
1104
+ // Walk light DOM children (slotted page components like docs-home, ui-showcase)
1105
+ walk(this);
1106
+ // Walk shadow DOM content (internal layout elements)
1107
+ if (this.shadowRoot) {
1108
+ walk(this.shadowRoot);
1109
+ }
1110
+ }
1111
+ /**
1112
+ * Recursively search for open-layout in parsed DOM, including
1113
+ * inside <template shadowrootmode="open"> (DSD content).
1114
+ *
1115
+ * querySelector does not traverse template content, but SSG pages
1116
+ * wrap page output in a page component whose shadow root contains
1117
+ * the <open-layout>.
1118
+ */ _findOpenLayout(root) {
1119
+ for (const child of Array.from(root.children)){
1120
+ if (child.tagName.toLowerCase() === 'open-layout') return child;
1121
+ if (child.tagName === 'TEMPLATE') {
1122
+ const found = this._findOpenLayout(child.content);
1123
+ if (found) return found;
1124
+ }
1125
+ const found = this._findOpenLayout(child);
1126
+ if (found) return found;
1127
+ }
1128
+ return null;
1129
+ }
1130
+ _activateDeclarativeShadowRoots(root) {
1131
+ const templates = Array.from(root.querySelectorAll('template[shadowrootmode]'));
1132
+ if (root instanceof HTMLElement && root.firstElementChild instanceof HTMLTemplateElement && root.firstElementChild.hasAttribute('shadowrootmode')) {
1133
+ templates.unshift(root.firstElementChild);
1134
+ }
1135
+ for (const template of templates){
1136
+ const host = template.parentElement;
1137
+ if (!host || host.shadowRoot) {
1138
+ template.remove();
1139
+ continue;
1140
+ }
1141
+ const mode = template.getAttribute('shadowrootmode') === 'closed' ? 'closed' : 'open';
1142
+ const shadow = host.attachShadow({
1143
+ mode
1144
+ });
1145
+ shadow.appendChild(template.content);
1146
+ template.remove();
1147
+ }
1148
+ }
1149
+ _isShadowTemplate(el) {
1150
+ return el instanceof HTMLTemplateElement && el.hasAttribute('shadowrootmode');
1151
+ }
1152
+ _syncLayoutAttributes(newLayout, locale) {
1153
+ const incoming = new Set(Array.from(newLayout.attributes).map((attr)=>attr.name));
1154
+ const preserve = new Set([
1155
+ 'data-theme',
1156
+ 'theme'
1157
+ ]);
1158
+ for (const attr of Array.from(this.attributes)){
1159
+ if (!incoming.has(attr.name) && !preserve.has(attr.name)) {
1160
+ this.removeAttribute(attr.name);
1161
+ }
1162
+ }
1163
+ for (const attr of Array.from(newLayout.attributes)){
1164
+ this.setAttribute(attr.name, attr.value);
1165
+ }
1166
+ this.setAttribute('locale', locale);
1167
+ this.setAttribute('current-path', newLayout.getAttribute('current-path') || this._currentPathWithoutLocale);
1168
+ }
1169
+ _replaceShadowRootFromLayout(newLayout) {
1170
+ const shadowTemplate = Array.from(newLayout.children).find((child)=>this._isShadowTemplate(child));
1171
+ if (!shadowTemplate || !this.shadowRoot) return;
1172
+ while(this.shadowRoot.firstChild){
1173
+ this.shadowRoot.removeChild(this.shadowRoot.firstChild);
1174
+ }
1175
+ this.shadowRoot.appendChild(document.adoptNode(shadowTemplate.content));
1176
+ this._activateDeclarativeShadowRoots(this.shadowRoot);
1177
+ this._setupDetailsToggle();
1178
+ this._updateSwitch(this.shadowRoot);
1179
+ }
1180
+ /* --- SPA navigation (inlined from @openelement/router) --- */ _setupSpaNavigation(opts) {
1181
+ this._navOptions = opts;
1182
+ if (this.shadowRoot) {
1183
+ this._setupClickDelegation(this.shadowRoot);
1184
+ }
1185
+ this._setupNavigationApi();
1186
+ this._setupPopState();
1187
+ }
1188
+ _teardownSpaNavigation() {
1189
+ this._cleanupNav?.();
1190
+ this._cleanupNav = undefined;
1191
+ this._navOptions = undefined;
1192
+ }
1193
+ _setupClickDelegation(root) {
1194
+ const handler = (e)=>{
1195
+ const link = e.target.closest('a');
1196
+ if (!link) return;
1197
+ const href = link.getAttribute('href');
1198
+ if (!href) return;
1199
+ if (!isSafeLayoutUrl(href) || /^https?:/i.test(href) || href.startsWith('#')) {
1200
+ return;
1201
+ }
1202
+ e.preventDefault();
1203
+ e.stopImmediatePropagation();
1204
+ const isLangSwitch = link.classList.contains('lang-switch');
1205
+ if (isLangSwitch) {
1206
+ this._replaceTo(href);
1207
+ } else {
1208
+ this._navigateTo(href);
1209
+ }
1210
+ };
1211
+ root.addEventListener('click', handler);
1212
+ const prev = this._cleanupNav;
1213
+ this._cleanupNav = ()=>{
1214
+ root.removeEventListener('click', handler);
1215
+ prev?.();
1216
+ };
1217
+ }
1218
+ _setupNavigationApi() {
1219
+ const nav1 = globalThis.navigation;
1220
+ if (!nav1) return;
1221
+ const onNav = (event)=>{
1222
+ const e = event;
1223
+ if (!e.canIntercept || e.hashChange || e.downloadRequest) return;
1224
+ const url = new URL(e.destination.url);
1225
+ if (url.origin !== location.origin) return;
1226
+ e.intercept({
1227
+ handler: ()=>this._navigateNow(url.pathname)
1228
+ });
1229
+ };
1230
+ try {
1231
+ nav1.addEventListener('navigate', onNav);
1232
+ const prev = this._cleanupNav;
1233
+ this._cleanupNav = ()=>{
1234
+ try {
1235
+ nav1.removeEventListener('navigate', onNav);
1236
+ } catch {}
1237
+ prev?.();
1238
+ };
1239
+ } catch {
1240
+ // Navigation API interception is optional; fall back to popstate routing.
1241
+ }
1242
+ }
1243
+ _setupPopState() {
1244
+ const handler = ()=>{
1245
+ this._navigateNow(location.pathname);
1246
+ };
1247
+ globalThis.addEventListener('popstate', handler);
1248
+ const prev = this._cleanupNav;
1249
+ this._cleanupNav = ()=>{
1250
+ globalThis.removeEventListener('popstate', handler);
1251
+ prev?.();
1252
+ };
1253
+ }
1254
+ _navigateTo(href) {
1255
+ const url = new URL(href, location.origin);
1256
+ if (url.origin !== location.origin) {
1257
+ location.href = href;
1258
+ return;
1259
+ }
1260
+ history.pushState(null, '', url.pathname + url.search + url.hash);
1261
+ this._navigateNow(url.pathname);
1262
+ }
1263
+ _replaceTo(href) {
1264
+ const url = new URL(href, location.origin);
1265
+ if (url.origin !== location.origin) return;
1266
+ history.replaceState(null, '', url.pathname + url.search + url.hash);
1267
+ this._navigateNow(url.pathname);
1268
+ }
1269
+ _navigateNow(pathname) {
1270
+ const locale = detectLocale(pathname, this._locales, this._defaultLocale);
1271
+ this.setAttribute('current-path', pathname);
1272
+ this.setAttribute('locale', locale);
1273
+ const opts = this._navOptions;
1274
+ if (!opts) return;
1275
+ // Update lang-switch immediately (before async fetch)
1276
+ if (this.shadowRoot) {
1277
+ this._updateSwitch(this.shadowRoot);
1278
+ }
1279
+ opts.contentLoader(pathname, locale).then(()=>{
1280
+ if (this.shadowRoot) {
1281
+ this._updateSwitch(this.shadowRoot);
1282
+ }
1283
+ opts.onAfterSwap?.(pathname, locale);
1284
+ }).catch((err)=>{
1285
+ log.warn('content load failed:', err);
1286
+ location.reload();
1287
+ });
1288
+ }
1289
+ _updateSwitch(shadowRoot) {
1290
+ const link = shadowRoot.querySelector('.lang-switch');
1291
+ if (!link) return;
1292
+ const pathWithoutLocale = this._currentPathWithoutLocale;
1293
+ const currentLocale = this._currentLocale;
1294
+ link.textContent = switchLabel(currentLocale);
1295
+ link.setAttribute('href', switchPath(pathWithoutLocale, currentLocale, this._locales));
1296
+ }
1297
+ async _loadContent(path1, locale) {
1298
+ try {
1299
+ const resp = await fetch(path1);
1300
+ if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
1301
+ const html = await resp.text();
1302
+ const parsed = new DOMParser().parseFromString(html, 'text/html');
1303
+ const tmp = parsed.body;
1304
+ const newLayout = this._findOpenLayout(tmp);
1305
+ if (!newLayout) throw new Error('No open-layout found');
1306
+ document.documentElement.lang = parsed.documentElement.lang || locale;
1307
+ if (parsed.title) document.title = parsed.title;
1308
+ this._syncHeadElement(parsed, 'meta[name="description"]');
1309
+ this._syncHeadElement(parsed, 'link[rel="canonical"]');
1310
+ this._syncHeadElements(parsed, 'link[rel="alternate"][hreflang]');
1311
+ this._syncLayoutAttributes(newLayout, locale);
1312
+ this._replaceShadowRootFromLayout(newLayout);
1313
+ // DOMParser nodes belong to a different document. adoptNode()
1314
+ // transfers ownership so appendChild works without errors.
1315
+ while(this.firstChild)this.removeChild(this.firstChild);
1316
+ const children = Array.from(newLayout.children).filter((child)=>!this._isShadowTemplate(child));
1317
+ for (const child of children){
1318
+ const adopted = document.adoptNode(child);
1319
+ if (adopted instanceof Element) {
1320
+ this._activateDeclarativeShadowRoots(adopted);
1321
+ }
1322
+ this.appendChild(adopted);
1323
+ }
1324
+ // Propagate theme to newly inserted components.
1325
+ const currentTheme = this.getAttribute('data-theme') || document.documentElement?.dataset?.theme;
1326
+ if (currentTheme) {
1327
+ this._propagateTheme(currentTheme);
1328
+ requestAnimationFrame(()=>this._propagateTheme(currentTheme));
1329
+ }
1330
+ globalThis.scrollTo({
1331
+ top: 0,
1332
+ behavior: 'smooth'
1333
+ });
1334
+ } catch (e) {
1335
+ log.warn('SPA navigation failed, reloading:', e);
1336
+ globalThis.location.reload();
1337
+ }
1338
+ }
1339
+ _syncHeadElement(parsed, selector) {
1340
+ const incoming = parsed.head.querySelector(selector);
1341
+ const current = document.head.querySelector(selector);
1342
+ if (!incoming) {
1343
+ current?.remove();
1344
+ return;
1345
+ }
1346
+ const cloned = document.adoptNode(incoming.cloneNode(true));
1347
+ if (current) current.replaceWith(cloned);
1348
+ else document.head.appendChild(cloned);
1349
+ }
1350
+ _syncHeadElements(parsed, selector) {
1351
+ document.head.querySelectorAll(selector).forEach((el)=>el.remove());
1352
+ parsed.head.querySelectorAll(selector).forEach((el)=>{
1353
+ document.head.appendChild(document.adoptNode(el.cloneNode(true)));
1354
+ });
1355
+ }
1356
+ _updateActiveNav() {
1357
+ if (!this.shadowRoot) return;
1358
+ const cp = this._currentPath();
1359
+ const links = this.shadowRoot.querySelectorAll('.docs-sidebar a[data-nav], .header-nav a[data-nav]');
1360
+ links.forEach((a1)=>{
1361
+ const nav1 = a1.getAttribute('data-nav');
1362
+ const isActive = nav1 === cp;
1363
+ a1.classList.toggle('active', isActive);
1364
+ if (isActive) a1.setAttribute('aria-current', 'page');
1365
+ else a1.removeAttribute('aria-current');
1366
+ });
1367
+ }
1368
+ // --- Utilities ---
1369
+ _esc = escapeHtml;
1370
+ _escAttr = escapeAttr;
1371
+ }
1372
+ export default OpenLayout;
1373
+ // Guard: idempotent across SSR paths
1374
+ if (typeof customElements !== 'undefined' && !customElements.get(tagName)) {
1375
+ customElements.define(tagName, OpenLayout);
1376
+ }
1377
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy91aS9zcmMvb3Blbi1sYXlvdXQudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qKiBAanN4SW1wb3J0U291cmNlIEBvcGVuZWxlbWVudC9jb3JlICovXG4vKipcbiAqIEBvcGVuZWxlbWVudC91aSAtIG9wZW4tbGF5b3V0XG4gKlxuICogQXBwIGxheW91dCBjb21wb25lbnQgd2l0aCBoZWFkZXIsIHNpZGViYXIsIGFuZCBmb290ZXIuXG4gKiBXZWIgU3RhbmRhcmRzIExhYjogbGlnaHQtZmlyc3QsIHJlc3RyYWluZWQsIGRvY3VtZW50YXRpb24tZm9jdXNlZC5cbiAqXG4gKiB2MC4yMC4wOiBNaWdyYXRlZCBmcm9tIERzZExpdEVsZW1lbnQgdG8gRHNkRWxlbWVudCAoT2NlYW4gY29tcG9uZW50KS5cbiAqICAgLSBDU1NTdHlsZVNoZWV0IHJlcGxhY2VzIExpdCBjc3NgYFxuICogICAtIHJlbmRlcigpIHJldHVybnMgc3RyaW5nXG4gKiAgIC0gQGNsaWNrIGJpbmRpbmdzIGZvciBtb2JpbGUgbWVudSB0b2dnbGVcbiAqICAgLSBTUEEgbmF2aWdhdGlvbiB2aWEgTmF2aWdhdGlvbiBBUEkgKG5hdmlnYXRlL2ZldGNoL3N3YXApIHByZXNlcnZlZFxuICogICAtIEV2ZW50IGRlbGVnYXRpb24gYXQgc2hhZG93IHJvb3QgbGV2ZWwgZm9yIG5hdiBjbGlja3NcbiAqIHYwLjI0LjE6IE1pZ3JhdGVkIGZyb20gaHRtbGBgIHRlbXBsYXRlIHRvIEpTWCAoQURSLTAwNTcpLlxuICpcbiAqIEBjc3NwYXJ0IGNvbnRhaW5lciAtIFRoZSBhcHAtbGF5b3V0IHJvb3QgZGl2XG4gKiBAY3NzcGFydCBoZWFkZXIgLSBUaGUgc3RpY2t5IGhlYWRlciBlbGVtZW50XG4gKiBAY3NzcGFydCBzaWRlYmFyIC0gVGhlIGRvY3Mtc2lkZWJhciBuYXZcbiAqIEBjc3NwYXJ0IG1haW4gLSBUaGUgbGF5b3V0LW1haW4gZWxlbWVudFxuICogQGNzc3BhcnQgZm9vdGVyIC0gVGhlIGFwcC1mb290ZXIgZWxlbWVudFxuICogQGNzc3BhcnQgbmF2IC0gVGhlIGhlYWRlci1uYXYgZWxlbWVudFxuICogQGNzc3BhcnQgbmF2LXRvZ2dsZSAtIFRoZSBtb2JpbGUgbWVudSB0b2dnbGUgYnV0dG9uXG4gKlxuICogVXNhZ2U6XG4gKiBgYGBodG1sXG4gKiA8b3Blbi1sYXlvdXQgY3VycmVudC1wYXRoPVwiL2d1aWRlL2dldHRpbmctc3RhcnRlZFwiXG4gKiAgIG5hdi1pdGVtcz0nW3tcInNlY3Rpb25cIjpcIkd1aWRlXCIsXCJpdGVtc1wiOlt7XCJwYXRoXCI6XCIvZ3VpZGUvZ2V0dGluZy1zdGFydGVkXCIsXCJsYWJlbFwiOlwiR2V0dGluZyBTdGFydGVkXCJ9XX1dJz5cbiAqIDwvb3Blbi1sYXlvdXQ+XG4gKiBgYGBcbiAqL1xuXG5pbXBvcnQgeyBPcGVuRWxlbWVudCB9IGZyb20gJ0BvcGVuZWxlbWVudC9lbGVtZW50JztcbmltcG9ydCB7IFN0eWxlU2hlZXQsIHR5cGUgU3R5bGVTaGVldExpa2UgfSBmcm9tICdAb3BlbmVsZW1lbnQvY29yZS9zdHlsZS1zaGVldCc7XG5pbXBvcnQgeyB0eXBlIENvbnRleHQsIGNyZWF0ZUNvbnRleHQsIHByb3ZpZGVDb250ZXh0IH0gZnJvbSAnQG9wZW5lbGVtZW50L2NvcmUnO1xuaW1wb3J0IHsgZXNjYXBlQXR0ciwgZXNjYXBlSHRtbCB9IGZyb20gJ0BvcGVuZWxlbWVudC9jb3JlJztcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gJ0BvcGVuZWxlbWVudC9jb3JlL2xvZ2dlcic7XG5pbXBvcnQgJy5cXC9vcGVuLXRoZW1lLXRvZ2dsZS5qcyc7XG5pbXBvcnQgJy4vb3Blbi1icmFuZC1tYXJrLmpzJztcblxuZXhwb3J0IGNvbnN0IHRhZ05hbWUgPSAnb3Blbi1sYXlvdXQnO1xuY29uc3QgU0FGRV9VUkxfU0NIRU1FUyA9IG5ldyBTZXQoWydodHRwOicsICdodHRwczonLCAnbWFpbHRvOicsICd0ZWw6JywgJ3NtczonXSk7XG5jb25zdCBsb2cgPSBjcmVhdGVMb2dnZXIoJ3VpJyk7XG5cbmZ1bmN0aW9uIGlzU2FmZUxheW91dFVybCh1cmw6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCB0cmltbWVkID0gdXJsLnRyaW0oKTtcbiAgaWYgKCF0cmltbWVkKSByZXR1cm4gZmFsc2U7XG4gIGlmICh0cmltbWVkLnN0YXJ0c1dpdGgoJy8vJykpIHJldHVybiBmYWxzZTtcbiAgaWYgKFxuICAgIHRyaW1tZWQuc3RhcnRzV2l0aCgnLycpIHx8XG4gICAgdHJpbW1lZC5zdGFydHNXaXRoKCcjJykgfHxcbiAgICB0cmltbWVkLnN0YXJ0c1dpdGgoJy4vJykgfHxcbiAgICB0cmltbWVkLnN0YXJ0c1dpdGgoJy4uLycpXG4gICkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHRyeSB7XG4gICAgY29uc3QgcGFyc2VkID0gbmV3IFVSTCh0cmltbWVkLCAnaHR0cHM6Ly9vcGVuZWxlbWVudC5vcmcvJyk7XG4gICAgcmV0dXJuIFNBRkVfVVJMX1NDSEVNRVMuaGFzKHBhcnNlZC5wcm90b2NvbCk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vKiAtLS0gTmF2aWdhdGlvbiBBUEkgdHlwZXMgKGZvciBTUEEgcm91dGluZykgLS0tICovXG5pbnRlcmZhY2UgTmF2aWdhdGlvbkxpa2UgZXh0ZW5kcyBFdmVudFRhcmdldCB7XG4gIGFkZEV2ZW50TGlzdGVuZXIodHlwZTogJ25hdmlnYXRlJywgbGlzdGVuZXI6IEV2ZW50TGlzdGVuZXIpOiB2b2lkO1xuICByZW1vdmVFdmVudExpc3RlbmVyKHR5cGU6ICduYXZpZ2F0ZScsIGxpc3RlbmVyOiBFdmVudExpc3RlbmVyKTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIE5hdmlnYXRpb25OYXZpZ2F0ZUV2ZW50IGV4dGVuZHMgRXZlbnQge1xuICBjYW5JbnRlcmNlcHQ6IGJvb2xlYW47XG4gIGhhc2hDaGFuZ2U6IGJvb2xlYW47XG4gIGRvd25sb2FkUmVxdWVzdDogYm9vbGVhbjtcbiAgZGVzdGluYXRpb246IHsgdXJsOiBzdHJpbmcgfTtcbiAgaW50ZXJjZXB0KG9wdHM6IHsgaGFuZGxlcjogKCkgPT4gdm9pZCB9KTogdm9pZDtcbn1cblxuLyogLS0tIExvY2FsZS9wYXRoIGhlbHBlcnMgKGlubGluZWQgZnJvbSBAb3BlbmVsZW1lbnQvcm91dGVyKSAtLS0gKi9cblxuY29uc3QgTE9DQUxFX0xBQkVMUzogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHsgZW46ICfkuK3mlocnLCB6aDogJ0VuZ2xpc2gnIH07XG5cbmZ1bmN0aW9uIHBhcnNlUGF0aFdpdGhvdXRMb2NhbGUocGF0aG5hbWU6IHN0cmluZywgbG9jYWxlczogc3RyaW5nW10pOiBzdHJpbmcge1xuICBjb25zdCBzZWdzID0gcGF0aG5hbWUuc3BsaXQoJy8nKS5maWx0ZXIoQm9vbGVhbik7XG4gIGlmIChzZWdzLmxlbmd0aCA+IDAgJiYgbG9jYWxlcy5pbmNsdWRlcyhzZWdzWzBdKSkge1xuICAgIHJldHVybiAnLycgKyBzZWdzLnNsaWNlKDEpLmpvaW4oJy8nKSB8fCAnLyc7XG4gIH1cbiAgcmV0dXJuIHBhdGhuYW1lIHx8ICcvJztcbn1cblxuZnVuY3Rpb24gZGV0ZWN0TG9jYWxlKHBhdGhuYW1lOiBzdHJpbmcsIGxvY2FsZXM6IHN0cmluZ1tdLCBkZWZhdWx0TG9jYWxlOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBzZWdzID0gcGF0aG5hbWUuc3BsaXQoJy8nKS5maWx0ZXIoQm9vbGVhbik7XG4gIGlmIChzZWdzLmxlbmd0aCA+IDAgJiYgbG9jYWxlcy5pbmNsdWRlcyhzZWdzWzBdKSkgcmV0dXJuIHNlZ3NbMF07XG4gIHJldHVybiBkZWZhdWx0TG9jYWxlO1xufVxuXG5mdW5jdGlvbiBsb2NhbGl6ZVBhdGgocGF0aDogc3RyaW5nLCBsb2NhbGU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmIChpc1NhZmVMYXlvdXRVcmwocGF0aCkgJiYgL15odHRwcz86L2kudGVzdChwYXRoKSkgcmV0dXJuIHBhdGg7XG4gIHJldHVybiBgLyR7bG9jYWxlfSR7cGF0aH1gO1xufVxuXG5mdW5jdGlvbiBzd2l0Y2hQYXRoKGN1cnJlbnRQYXRoOiBzdHJpbmcsIGN1cnJlbnRMb2NhbGU6IHN0cmluZywgbG9jYWxlczogc3RyaW5nW10pOiBzdHJpbmcge1xuICBjb25zdCBvdGhlciA9IGxvY2FsZXMuZmluZCgobCkgPT4gbCAhPT0gY3VycmVudExvY2FsZSkgfHwgY3VycmVudExvY2FsZTtcbiAgcmV0dXJuIGAvJHtvdGhlcn0ke2N1cnJlbnRQYXRofWA7XG59XG5cbmZ1bmN0aW9uIHN3aXRjaExhYmVsKGN1cnJlbnRMb2NhbGU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBMT0NBTEVfTEFCRUxTW2N1cnJlbnRMb2NhbGVdIHx8IGN1cnJlbnRMb2NhbGU7XG59XG5cbi8qKiBTaWduYWxDb250ZXh0IGtleTogdGhlbWUgc3RhdGUgc2hhcmVkIGFjcm9zcyBhbGwgY29tcG9uZW50cyAqL1xuZXhwb3J0IGNvbnN0IFRIRU1FX0NUWDogQ29udGV4dDwnZGFyaycgfCAnbGlnaHQnPiA9IGNyZWF0ZUNvbnRleHQ8J2RhcmsnIHwgJ2xpZ2h0Jz4oXG4gIFN5bWJvbCgndGhlbWUnKSxcbiAgJ2xpZ2h0Jyxcbik7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmF2SXRlbSB7XG4gIHBhdGg/OiBzdHJpbmc7XG4gIGhyZWY/OiBzdHJpbmc7XG4gIGxhYmVsOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTmF2U2VjdGlvbiB7XG4gIHNlY3Rpb246IHN0cmluZztcbiAgaXRlbXM6IE5hdkl0ZW1bXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBIZWFkZXJOYXZMaW5rIHtcbiAgaHJlZjogc3RyaW5nO1xuICBsYWJlbDogc3RyaW5nO1xufVxuXG5jb25zdCBzaGVldDogU3R5bGVTaGVldExpa2UgPSBuZXcgU3R5bGVTaGVldCgpO1xuc2hlZXQucmVwbGFjZVN5bmMoYFxuICA6aG9zdCB7XG4gICAgZGlzcGxheTogYmxvY2s7XG4gIH1cblxuICAqIHsgZm9udC1mYW1pbHk6IHZhcigtLWZvbnQtc2Fucyk7IH1cblxuICAuYXBwLWxheW91dCB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgIG1pbi1oZWlnaHQ6IDEwMHZoO1xuICAgIGJhY2tncm91bmQ6IHZhcigtLWJnLWJhc2UpO1xuICAgIGNvbG9yOiB2YXIoLS10ZXh0LXByaW1hcnkpO1xuICAgIGZvbnQtZmFtaWx5OiB2YXIoLS1mb250LXNhbnMpO1xuICAgIC13ZWJraXQtZm9udC1zbW9vdGhpbmc6IGFudGlhbGlhc2VkO1xuICAgIC1tb3otb3N4LWZvbnQtc21vb3RoaW5nOiBncmF5c2NhbGU7XG4gIH1cblxuICAubGF5b3V0LWJvZHkge1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgZmxleDogMTtcbiAgICBtYXgtd2lkdGg6IDE0MDBweDtcbiAgICBtYXJnaW46IDAgYXV0bztcbiAgICB3aWR0aDogMTAwJTtcbiAgfVxuXG4gIC5sYXlvdXQtbWFpbiB7XG4gICAgZmxleDogMTtcbiAgICBtaW4td2lkdGg6IDA7XG4gICAgd2lkdGg6IDEwMCU7XG4gIH1cblxuICAuYXBwLWxheW91dFtob21lXSAubGF5b3V0LWJvZHksXG4gIC5hcHAtbGF5b3V0W2Z1bGwtd2lkdGhdIC5sYXlvdXQtYm9keSB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgIG1heC13aWR0aDogbm9uZTtcbiAgfVxuXG4gIC5hcHAtbGF5b3V0W2hvbWVdIC5sYXlvdXQtbWFpbixcbiAgLmFwcC1sYXlvdXRbZnVsbC13aWR0aF0gLmxheW91dC1tYWluIHtcbiAgICBmbGV4OiAxO1xuICB9XG5cbiAgLyogSGVhZGVyICovXG4gIC5hcHAtaGVhZGVyIHtcbiAgICBwb3NpdGlvbjogc3RpY2t5O1xuICAgIHRvcDogMDtcbiAgICB6LWluZGV4OiAxMDA7XG4gICAgYmFja2dyb3VuZDogdmFyKC0tbmF2LWJnKTtcbiAgICBib3JkZXItYm90dG9tOiB2YXIoLS1ib3JkZXItc2l6ZS0xKSBzb2xpZCB2YXIoLS1ib3JkZXIpO1xuICAgIGJhY2tkcm9wLWZpbHRlcjogYmx1cigxOHB4KSBzYXR1cmF0ZSgxNTAlKTtcbiAgICAtd2Via2l0LWJhY2tkcm9wLWZpbHRlcjogYmx1cigxOHB4KSBzYXR1cmF0ZSgxNTAlKTtcbiAgICB0cmFuc2l0aW9uOiBiYWNrZ3JvdW5kIDAuMnMgZWFzZSwgYm9yZGVyLWNvbG9yIDAuMnMgZWFzZSwgYm94LXNoYWRvdyAwLjJzIGVhc2U7XG4gIH1cbiAgLmFwcC1oZWFkZXIuc2Nyb2xsZWQge1xuICAgIGJhY2tncm91bmQ6IGNvbG9yLW1peChpbiBzcmdiLCB2YXIoLS1iZy1iYXNlKSA4OCUsIHRyYW5zcGFyZW50KTtcbiAgICBib3JkZXItYm90dG9tLWNvbG9yOiB2YXIoLS1ib3JkZXItaG92ZXIpO1xuICAgIGJveC1zaGFkb3c6IDAgdmFyKC0tc2l6ZS0yKSB2YXIoLS1zaXplLTEwKSBjb2xvci1taXgoaW4gc3JnYiwgdmFyKC0tYnJhbmQpIDUlLCB0cmFuc3BhcmVudCk7XG4gIH1cblxuICAuaGVhZGVyLWlubmVyIHtcbiAgICBtYXgtd2lkdGg6IG5vbmU7XG4gICAgbWFyZ2luOiAwIGF1dG87XG4gICAgcGFkZGluZzogMCBjbGFtcCh2YXIoLS1zaXplLTUpLCAzLjV2dywgdmFyKC0tc2l6ZS05KSk7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIG1pbi1oZWlnaHQ6IHZhcigtLW5hdi1oZWlnaHQpO1xuICAgIGdhcDogdmFyKC0tc2l6ZS02KTtcbiAgfVxuXG4gIC5tb2JpbGUtdGFiLWJhciB7IGRpc3BsYXk6IG5vbmU7IH1cblxuICAubW9iaWxlLW1lbnUtYnRuIHtcbiAgICBkaXNwbGF5OiBub25lO1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gICAgd2lkdGg6IHZhcigtLXNpemUtMTApO1xuICAgIGhlaWdodDogdmFyKC0tc2l6ZS0xMCk7XG4gICAgYm9yZGVyOiB2YXIoLS1ib3JkZXItc2l6ZS0xKSBzb2xpZCB2YXIoLS1ib3JkZXIpO1xuICAgIGJvcmRlci1yYWRpdXM6IHZhcigtLXJhZGl1cy1yb3VuZCk7XG4gICAgYmFja2dyb3VuZDogY29sb3ItbWl4KGluIHNyZ2IsIHZhcigtLWJnLWVsZXZhdGVkKSA3NCUsIHRyYW5zcGFyZW50KTtcbiAgICBjb2xvcjogdmFyKC0tdGV4dC1zZWNvbmRhcnkpO1xuICAgIGN1cnNvcjogcG9pbnRlcjtcbiAgICBwYWRkaW5nOiAwO1xuICAgIHRyYW5zaXRpb246IGFsbCAwLjE1cyBlYXNlO1xuICB9XG4gIC5tb2JpbGUtbWVudS1idG46aG92ZXIge1xuICAgIGNvbG9yOiB2YXIoLS10ZXh0LXByaW1hcnkpO1xuICAgIGJvcmRlci1jb2xvcjogdmFyKC0tYm9yZGVyLWhvdmVyKTtcbiAgICBiYWNrZ3JvdW5kOiB2YXIoLS1iZy1ob3Zlcik7XG4gIH1cblxuICAubG9nbyB7XG4gICAgZGlzcGxheTogaW5saW5lLWZsZXg7XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICBnYXA6IHZhcigtLXNpemUtMyk7XG4gICAgZm9udC1zaXplOiB2YXIoLS1mb250LXNpemUtMyk7XG4gICAgZm9udC13ZWlnaHQ6IHZhcigtLWZvbnQtd2VpZ2h0LTgpO1xuICAgIGNvbG9yOiB2YXIoLS10ZXh0LXByaW1hcnkpO1xuICAgIHRleHQtZGVjb3JhdGlvbjogbm9uZTtcbiAgICBsZXR0ZXItc3BhY2luZzogMDtcbiAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICB9XG5cbiAgLmxvZ286aG92ZXIgb3Blbi1icmFuZC1tYXJrIHtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoY2FsYyh2YXIoLS1ib3JkZXItc2l6ZS0xKSAqIC0xKSk7XG4gIH1cblxuICBvcGVuLWJyYW5kLW1hcmsge1xuICAgIHRyYW5zaXRpb246IHRyYW5zZm9ybSB2YXIoLS1kdXJhdGlvbi0yKSB2YXIoLS1lYXNlLTIpO1xuICB9XG5cbiAgLmxvZ28td29yZCB7XG4gICAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWShjYWxjKHZhcigtLWJvcmRlci1zaXplLTEpICogLTEpKTtcbiAgfVxuXG4gIC5sb2dvLXN1YiB7XG4gICAgZm9udC1zaXplOiB2YXIoLS1mb250LXNpemUtMDApO1xuICAgIGNvbG9yOiB2YXIoLS10ZXh0LW11dGVkKTtcbiAgICBtYXJnaW4tbGVmdDogdmFyKC0tc2l6ZS0yKTtcbiAgICBmb250LWZhbWlseTogdmFyKC0tZm9udC1tb25vKTtcbiAgICBmb250LXdlaWdodDogdmFyKC0tZm9udC13ZWlnaHQtOCk7XG4gICAgdGV4dC10cmFuc2Zvcm06IHVwcGVyY2FzZTtcbiAgfVxuXG4gIC5oZWFkZXItbmF2IHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGdhcDogY2xhbXAodmFyKC0tc2l6ZS01KSwgM3Z3LCB2YXIoLS1zaXplLTgpKTtcbiAgICBmbGV4OiAxO1xuICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICB9XG4gIC5oZWFkZXItbmF2IGEge1xuICAgIGNvbG9yOiB2YXIoLS1uYXYtbGluay1jb2xvcik7XG4gICAgdGV4dC1kZWNvcmF0aW9uOiBub25lO1xuICAgIGZvbnQtc2l6ZTogdmFyKC0tZm9udC1zaXplLTEpO1xuICAgIGZvbnQtd2VpZ2h0OiB2YXIoLS1mb250LXdlaWdodC01KTtcbiAgICBwYWRkaW5nOiB2YXIoLS1zaXplLTIpIDA7XG4gICAgdHJhbnNpdGlvbjogY29sb3IgMC4xNXMgZWFzZSwgYmFja2dyb3VuZCAwLjE1cyBlYXNlO1xuICB9XG4gIC5oZWFkZXItbmF2IGE6aG92ZXIge1xuICAgIGNvbG9yOiB2YXIoLS1uYXYtbGluay1ob3Zlcik7XG4gIH1cbiAgLmhlYWRlci1uYXYgYVthcmlhLWN1cnJlbnQ9XCJwYWdlXCJdIHtcbiAgICBjb2xvcjogdmFyKC0tYnJhbmQtZGVlcCk7XG4gICAgZm9udC13ZWlnaHQ6IHZhcigtLWZvbnQtd2VpZ2h0LTgpO1xuICB9XG5cbiAgLmhlYWRlci1yaWdodCB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGdhcDogdmFyKC0tc2l6ZS0xKTtcbiAgICBtYXJnaW4tbGVmdDogYXV0bztcbiAgfVxuXG4gIC8qIENUQSBidXR0b25zICovXG4gIC5idG4tc2Vjb25kYXJ5IHtcbiAgICBkaXNwbGF5OiBpbmxpbmUtZmxleDtcbiAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgIGdhcDogdmFyKC0tc2l6ZS0yKTtcbiAgICBjb2xvcjogdmFyKC0tdGV4dC1wcmltYXJ5KTtcbiAgICB0ZXh0LWRlY29yYXRpb246IG5vbmU7XG4gICAgZm9udC1zaXplOiB2YXIoLS1mb250LXNpemUtYnV0dG9uKTtcbiAgICBmb250LXdlaWdodDogdmFyKC0tZm9udC13ZWlnaHQtc2VtaWJvbGQpO1xuICAgIHBhZGRpbmc6IHZhcigtLXNpemUtMikgdmFyKC0tc2l6ZS00KTtcbiAgICBib3JkZXI6IHZhcigtLWJvcmRlci1zaXplLTEpIHNvbGlkIGNvbG9yLW1peChpbiBzcmdiLCB2YXIoLS1ib3JkZXIpIDcyJSwgdmFyKC0tYnJhbmQpKTtcbiAgICBib3JkZXItcmFkaXVzOiB2YXIoLS1yYWRpdXMtcm91bmQpO1xuICAgIGJhY2tncm91bmQ6IGNvbG9yLW1peChpbiBzcmdiLCB2YXIoLS1iZy1lbGV2YXRlZCkgNzYlLCB0cmFuc3BhcmVudCk7XG4gICAgYm94LXNoYWRvdzogaW5zZXQgMCAxcHggMCBjb2xvci1taXgoaW4gc3JnYiwgdmFyKC0tZ3JheS0wKSA3MCUsIHRyYW5zcGFyZW50KTtcbiAgICB0cmFuc2l0aW9uOiBhbGwgMC4xNXMgZWFzZTtcbiAgfVxuICAuYnRuLXNlY29uZGFyeTpob3ZlciB7XG4gICAgY29sb3I6IHZhcigtLWJyYW5kLWRlZXApO1xuICAgIGJvcmRlci1jb2xvcjogdmFyKC0tYnJhbmQtbGlnaHQpO1xuICAgIGJhY2tncm91bmQ6IGNvbG9yLW1peChpbiBzcmdiLCB2YXIoLS1icmFuZC1wYWxlKSA0MiUsIHZhcigtLWJnLWVsZXZhdGVkKSk7XG4gIH1cbiAgLmJ0bi1zZWNvbmRhcnkgc3ZnIHsgZmxleC1zaHJpbms6IDA7IH1cblxuICAuYnRuLXByaW1hcnkge1xuICAgIGRpc3BsYXk6IGlubGluZS1mbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgZ2FwOiA0cHg7XG4gICAgY29sb3I6IHZhcigtLW9uLWJyYW5kKTtcbiAgICB0ZXh0LWRlY29yYXRpb246IG5vbmU7XG4gICAgZm9udC1zaXplOiB2YXIoLS1mb250LXNpemUtYnV0dG9uKTtcbiAgICBmb250LXdlaWdodDogdmFyKC0tZm9udC13ZWlnaHQtc2VtaWJvbGQpO1xuICAgIHBhZGRpbmc6IHZhcigtLXNpemUtMikgdmFyKC0tc2l6ZS00KTtcbiAgICBib3JkZXI6IHZhcigtLWJvcmRlci1zaXplLTEpIHNvbGlkIHRyYW5zcGFyZW50O1xuICAgIGJvcmRlci1yYWRpdXM6IHZhcigtLXJhZGl1cy1yb3VuZCk7XG4gICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgdmFyKC0tYnJhbmQpLCB2YXIoLS1icmFuZC1saWdodCkpO1xuICAgIGJveC1zaGFkb3c6IDAgdmFyKC0tc2l6ZS0yKSB2YXIoLS1zaXplLTUpIHZhcigtLWJyYW5kLWdsb3cpO1xuICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XG4gICAgdHJhbnNpdGlvbjogYWxsIDAuMTVzIGVhc2U7XG4gIH1cbiAgLmJ0bi1wcmltYXJ5OmhvdmVyIHtcbiAgICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCB2YXIoLS1icmFuZC1ob3ZlciksIHZhcigtLWJyYW5kLWxpZ2h0KSk7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKGNhbGModmFyKC0tYm9yZGVyLXNpemUtMSkgKiAtMSkpO1xuICB9XG5cbiAgLmhlYWRlci1yaWdodCAuYnRuLXNlY29uZGFyeSxcbiAgLmhlYWRlci1yaWdodCAuYnRuLXByaW1hcnkge1xuICAgIGRpc3BsYXk6IG5vbmU7XG4gIH1cblxuICAubGFuZy1zd2l0Y2gge1xuICAgIGRpc3BsYXk6IGlubGluZS1mbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gICAgbWluLXdpZHRoOiB2YXIoLS1zaXplLTkpO1xuICAgIHdpZHRoOiB2YXIoLS1zaXplLTkpO1xuICAgIGhlaWdodDogdmFyKC0tc2l6ZS05KTtcbiAgICBwYWRkaW5nOiAwO1xuICAgIGZvbnQtc2l6ZTogdmFyKC0tZm9udC1zaXplLWJ1dHRvbik7XG4gICAgZm9udC13ZWlnaHQ6IHZhcigtLWZvbnQtd2VpZ2h0LXNlbWlib2xkKTtcbiAgICBjb2xvcjogdmFyKC0tdGV4dC1zZWNvbmRhcnkpO1xuICAgIGJvcmRlcjogMDtcbiAgICBib3JkZXItcmFkaXVzOiB2YXIoLS1yYWRpdXMtcm91bmQpO1xuICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xuICAgIGN1cnNvcjogcG9pbnRlcjtcbiAgICB0ZXh0LWRlY29yYXRpb246IG5vbmU7XG4gICAgdHJhbnNpdGlvbjogYWxsIDAuMTVzIGVhc2U7XG4gIH1cbiAgLmxhbmctc3dpdGNoOmhvdmVyIHtcbiAgICBjb2xvcjogdmFyKC0tYnJhbmQtZGVlcCk7XG4gICAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgICBiYWNrZ3JvdW5kOiBjb2xvci1taXgoaW4gc3JnYiwgdmFyKC0tYnJhbmQtcGFsZSkgMzQlLCB0cmFuc3BhcmVudCk7XG4gIH1cblxuICAvKiBTaWRlYmFyICovXG4gIC5kb2NzLXNpZGViYXIge1xuICAgIHdpZHRoOiBjbGFtcCgyMDBweCwgMjB2dywgMjYwcHgpO1xuICAgIGZsZXgtc2hyaW5rOiAwO1xuICAgIGJvcmRlci1yaWdodDogdmFyKC0tYm9yZGVyLXNpemUtMSkgc29saWQgdmFyKC0tYm9yZGVyKTtcbiAgICBwYWRkaW5nOiAycmVtIDA7XG4gICAgb3ZlcmZsb3cteTogYXV0bztcbiAgICBoZWlnaHQ6IGNhbGMoMTAwdmggLSB2YXIoLS1uYXYtaGVpZ2h0KSk7XG4gICAgcG9zaXRpb246IHN0aWNreTtcbiAgICB0b3A6IHZhcigtLW5hdi1oZWlnaHQpO1xuICAgIHNjcm9sbGJhci13aWR0aDogdGhpbjtcbiAgICBiYWNrZ3JvdW5kOiBjb2xvci1taXgoaW4gc3JnYiwgdmFyKC0tYmctZWxldmF0ZWQpIDQyJSwgdHJhbnNwYXJlbnQpO1xuICB9XG4gIDpob3N0KFtob21lXSkgLmRvY3Mtc2lkZWJhcixcbiAgOmhvc3QoW2Z1bGwtd2lkdGhdKSAuZG9jcy1zaWRlYmFyIHtcbiAgICB3aWR0aDogMDsgbWluLXdpZHRoOiAwOyBwYWRkaW5nOiAwO1xuICAgIG92ZXJmbG93OiBoaWRkZW47IGJvcmRlci1yaWdodDogbm9uZTtcbiAgfVxuXG4gIC5uYXYtc2VjdGlvbiB7IG1hcmdpbi1ib3R0b206IDEuNXJlbTsgfVxuICAubmF2LXNlY3Rpb24gc3VtbWFyeSB7XG4gICAgZm9udC1zaXplOiAwLjYyNXJlbTtcbiAgICBmb250LXdlaWdodDogODAwO1xuICAgIHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7XG4gICAgbGV0dGVyLXNwYWNpbmc6IDAuMjJlbTtcbiAgICBjb2xvcjogdmFyKC0tdGV4dC1tdXRlZCk7XG4gICAgcGFkZGluZzogMCAxLjVyZW07XG4gICAgbWFyZ2luLWJvdHRvbTogMC41cmVtO1xuICAgIGN1cnNvcjogcG9pbnRlcjtcbiAgICBsaXN0LXN0eWxlOiBub25lO1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICBnYXA6IDAuNXJlbTtcbiAgICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgfVxuICAubmF2LXNlY3Rpb24gc3VtbWFyeTo6LXdlYmtpdC1kZXRhaWxzLW1hcmtlciB7IGRpc3BsYXk6IG5vbmU7IH1cbiAgLm5hdi1zZWN0aW9uIHN1bW1hcnk6Om1hcmtlciB7IGNvbnRlbnQ6IFwiXCI7IH1cbiAgLm5hdi1zZWN0aW9uIHN1bW1hcnk6aG92ZXIgeyBjb2xvcjogdmFyKC0tdGV4dC1zZWNvbmRhcnkpOyB9XG5cbiAgLmRvY3Mtc2lkZWJhciBhIHtcbiAgICBkaXNwbGF5OiBibG9jaztcbiAgICBjb2xvcjogdmFyKC0tdGV4dC1tdXRlZCk7XG4gICAgdGV4dC1kZWNvcmF0aW9uOiBub25lO1xuICAgIGZvbnQtc2l6ZTogMC44NXJlbTtcbiAgICBwYWRkaW5nOiAwLjM1cmVtIDEuNXJlbTtcbiAgICBib3JkZXItbGVmdDogMnB4IHNvbGlkIHRyYW5zcGFyZW50O1xuICAgIHRyYW5zaXRpb246IGNvbG9yIDAuMTVzIGVhc2UsIGJvcmRlci1jb2xvciAwLjE1cyBlYXNlLCBiYWNrZ3JvdW5kIDAuMTVzIGVhc2U7XG4gIH1cbiAgLmRvY3Mtc2lkZWJhciBhOmhvdmVyIHtcbiAgICBjb2xvcjogdmFyKC0tdGV4dC1zZWNvbmRhcnkpO1xuICAgIGJhY2tncm91bmQ6IHZhcigtLWJnLWhvdmVyKTtcbiAgfVxuICAuZG9jcy1zaWRlYmFyIGEuYWN0aXZlLFxuICAuZG9jcy1zaWRlYmFyIGFbYXJpYS1jdXJyZW50PVwicGFnZVwiXSB7XG4gICAgY29sb3I6IHZhcigtLWJyYW5kKTtcbiAgICBib3JkZXItbGVmdC1jb2xvcjogdmFyKC0tYnJhbmQpO1xuICAgIGJhY2tncm91bmQ6IHZhcigtLWJyYW5kLXN1YnRsZSk7XG4gICAgZm9udC13ZWlnaHQ6IDYwMDtcbiAgfVxuXG4gIC8qIEZvb3RlciAqL1xuICAuYXBwLWZvb3RlciB7XG4gICAgYm9yZGVyLXRvcDogdmFyKC0tYm9yZGVyLXNpemUtMSkgc29saWQgdmFyKC0tYm9yZGVyKTtcbiAgICBiYWNrZ3JvdW5kOiBjb2xvci1taXgoaW4gc3JnYiwgdmFyKC0tYmctZWxldmF0ZWQpIDU4JSwgdHJhbnNwYXJlbnQpO1xuICB9XG4gIC5mb290ZXItaW5uZXIge1xuICAgIG1heC13aWR0aDogMTI0MHB4O1xuICAgIG1hcmdpbjogMCBhdXRvO1xuICAgIHBhZGRpbmc6IHZhcigtLXNpemUtMTYpIHZhcigtLXNpemUtOCk7XG4gICAgZGlzcGxheTogZ3JpZDtcbiAgICBncmlkLXRlbXBsYXRlLWNvbHVtbnM6IHJlcGVhdCg0LCAxZnIpO1xuICAgIGdhcDogdmFyKC0tc2l6ZS04KTtcbiAgfVxuICAuZm9vdGVyLWNvbHVtbiBoNCB7XG4gICAgZm9udC1zaXplOiB2YXIoLS1mb250LXNpemUtYnV0dG9uKTtcbiAgICBmb250LXdlaWdodDogdmFyKC0tZm9udC13ZWlnaHQtc2VtaWJvbGQpO1xuICAgIGNvbG9yOiB2YXIoLS10ZXh0LXByaW1hcnkpO1xuICAgIG1hcmdpbjogMCAwIHZhcigtLXNpemUtNCk7XG4gIH1cbiAgLmZvb3Rlci1jb2x1bW4gYSB7XG4gICAgZGlzcGxheTogYmxvY2s7XG4gICAgY29sb3I6IHZhcigtLXRleHQtc2Vjb25kYXJ5KTtcbiAgICB0ZXh0LWRlY29yYXRpb246IG5vbmU7XG4gICAgZm9udC1zaXplOiB2YXIoLS1mb250LXNpemUtYm9keS1zbSk7XG4gICAgcGFkZGluZzogNHB4IDA7XG4gICAgdHJhbnNpdGlvbjogY29sb3IgMC4xNXMgZWFzZTtcbiAgfVxuICAuZm9vdGVyLWNvbHVtbiBhOmhvdmVyIHtcbiAgICBjb2xvcjogdmFyKC0tdGV4dC1wcmltYXJ5KTtcbiAgfVxuICAuZm9vdGVyLWJvdHRvbSB7XG4gICAgYm9yZGVyLXRvcDogdmFyKC0tYm9yZGVyLXNpemUtMSkgc29saWQgdmFyKC0tYm9yZGVyKTtcbiAgICBwYWRkaW5nOiB2YXIoLS1zaXplLTQpIHZhcigtLXNpemUtOCk7XG4gICAgbWF4LXdpZHRoOiAxMjQwcHg7XG4gICAgbWFyZ2luOiAwIGF1dG87XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICBjb2xvcjogdmFyKC0tdGV4dC1tdXRlZCk7XG4gICAgZm9udC1zaXplOiB2YXIoLS1mb250LXNpemUtYm9keS1zbSk7XG4gIH1cbiAgLmZvb3Rlci1ib3R0b20gYSB7XG4gICAgY29sb3I6IHZhcigtLXRleHQtc2Vjb25kYXJ5KTtcbiAgICB0ZXh0LWRlY29yYXRpb246IG5vbmU7XG4gICAgdHJhbnNpdGlvbjogY29sb3IgMC4xNXMgZWFzZTtcbiAgfVxuICAuZm9vdGVyLWJvdHRvbSBhOmhvdmVyIHtcbiAgICBjb2xvcjogdmFyKC0tdGV4dC1wcmltYXJ5KTtcbiAgfVxuXG4gIC8qIE1vYmlsZSBiYWNrZHJvcCAqL1xuICAubW9iaWxlLWJhY2tkcm9wIHtcbiAgICBwb3NpdGlvbjogZml4ZWQ7IGluc2V0OiAwOyB0b3A6IHZhcigtLW5hdi1oZWlnaHQpO1xuICAgIGJhY2tncm91bmQ6IHZhcigtLW92ZXJsYXkpO1xuICAgIHotaW5kZXg6IDgwOyBvcGFjaXR5OiAwOyBwb2ludGVyLWV2ZW50czogbm9uZTtcbiAgICB0cmFuc2l0aW9uOiBvcGFjaXR5IDAuM3MgZWFzZTtcbiAgfVxuXG4gIC8qIFJlc3BvbnNpdmUgKi9cbiAgQG1lZGlhIChtYXgtd2lkdGg6IDExMjBweCkge1xuICAgIC5oZWFkZXItaW5uZXIge1xuICAgICAgZ2FwOiB2YXIoLS1zaXplLTMpO1xuICAgICAgcGFkZGluZy1pbmxpbmU6IHZhcigtLXNpemUtNCk7XG4gICAgfVxuXG4gICAgLmhlYWRlci1uYXYge1xuICAgICAgZ2FwOiB2YXIoLS1zaXplLTMpO1xuICAgIH1cblxuICAgIC5idG4tc2Vjb25kYXJ5IC5idG4tdGV4dCB7IGRpc3BsYXk6IG5vbmU7IH1cbiAgfVxuXG4gIEBtZWRpYSAobWF4LXdpZHRoOiA5MDBweCkge1xuICAgIC5tb2JpbGUtbWVudS1idG4geyBkaXNwbGF5OiBmbGV4OyB9XG4gICAgLmhlYWRlci1pbm5lciB7IHBhZGRpbmc6IDAgdmFyKC0tc2l6ZS00KTsgZ2FwOiB2YXIoLS1zaXplLTIpOyB9XG4gICAgLmhlYWRlci1uYXYgeyBkaXNwbGF5OiBub25lOyB9XG4gICAgLmJ0bi1zZWNvbmRhcnkgLmJ0bi10ZXh0IHsgZGlzcGxheTogbm9uZTsgfVxuICAgIC5oZWFkZXItcmlnaHQgeyBnYXA6IDRweDsgfVxuXG4gICAgLmRvY3Mtc2lkZWJhciB7XG4gICAgICBwb3NpdGlvbjogZml4ZWQ7IHRvcDogdmFyKC0tbmF2LWhlaWdodCk7IGxlZnQ6IDA7XG4gICAgICB3aWR0aDogbWluKDI4MHB4LCA4MHZ3KTtcbiAgICAgIGhlaWdodDogY2FsYygxMDB2aCAtIHZhcigtLW5hdi1oZWlnaHQpKTsgei1pbmRleDogOTA7XG4gICAgICBiYWNrZ3JvdW5kOiB2YXIoLS1iZy1lbGV2YXRlZCk7XG4gICAgICBib3JkZXItcmlnaHQ6IHZhcigtLWJvcmRlci1zaXplLTEpIHNvbGlkIHZhcigtLWJvcmRlcik7XG4gICAgICBwYWRkaW5nOiAxcmVtIDA7IG92ZXJmbG93LXk6IGF1dG87XG4gICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTEwMSUpO1xuICAgICAgdHJhbnNpdGlvbjogdHJhbnNmb3JtIDAuMjVzIGN1YmljLWJlemllcigwLjQsMCwwLjIsMSk7XG4gICAgICB3aWxsLWNoYW5nZTogdHJhbnNmb3JtO1xuICAgIH1cbiAgICA6aG9zdChbbWVudS1vcGVuXSkgLmRvY3Mtc2lkZWJhciB7XG4gICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoMCk7XG4gICAgICBib3gtc2hhZG93OiB2YXIoLS1zaGFkb3ctMSk7XG4gICAgfVxuICAgIDpob3N0KFttZW51LW9wZW5dKSAubW9iaWxlLWJhY2tkcm9wIHsgb3BhY2l0eTogMTsgcG9pbnRlci1ldmVudHM6IGF1dG87IH1cbiAgICAubmF2LXNlY3Rpb24geyBtYXJnaW4tYm90dG9tOiAwLjVyZW07IH1cbiAgICAubmF2LXNlY3Rpb24gc3VtbWFyeSB7IHBhZGRpbmc6IHZhcigtLXNpemUtMikgdmFyKC0tc2l6ZS00KTsgfVxuICAgIC5kb2NzLXNpZGViYXIgYSB7IHBhZGRpbmc6IDAuNXJlbSAxcmVtIDAuNXJlbSAycmVtOyB9XG4gICAgLmxheW91dC1tYWluIHsgd2lkdGg6IDEwMCU7IH1cbiAgICAuYXBwLWZvb3RlciB7IHBhZGRpbmc6IDA7IH1cbiAgICAuZm9vdGVyLWlubmVyIHtcbiAgICAgIGdyaWQtdGVtcGxhdGUtY29sdW1uczogcmVwZWF0KDIsIDFmcik7XG4gICAgICBwYWRkaW5nOiB2YXIoLS1zaXplLTEyKSB2YXIoLS1zaXplLTQpO1xuICAgICAgcGFkZGluZy1ib3R0b206IGNhbGModmFyKC0tc2l6ZS0xMikgKyB2YXIoLS1zaXplLTE2KSk7XG4gICAgfVxuICAgIC5mb290ZXItYm90dG9tIHtcbiAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgICBnYXA6IHZhcigtLXNpemUtMik7XG4gICAgICBwYWRkaW5nOiB2YXIoLS1zaXplLTQpO1xuICAgICAgcGFkZGluZy1ib3R0b206IGNhbGModmFyKC0tc2l6ZS00KSArIHZhcigtLXNpemUtMTYpKTtcbiAgICAgIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgICB9XG5cbiAgICAubW9iaWxlLXRhYi1iYXIge1xuICAgICAgZGlzcGxheTogZmxleDsgcG9zaXRpb246IGZpeGVkOyBib3R0b206IDA7IGxlZnQ6IDA7IHJpZ2h0OiAwO1xuICAgICAgaGVpZ2h0OiA1NnB4OyB6LWluZGV4OiAxMDA7XG4gICAgICBiYWNrZ3JvdW5kOiB2YXIoLS1uYXYtYmcpO1xuICAgICAgYmFja2Ryb3AtZmlsdGVyOiBibHVyKDEycHgpIHNhdHVyYXRlKDE4MCUpO1xuICAgICAgLXdlYmtpdC1iYWNrZHJvcC1maWx0ZXI6IGJsdXIoMTJweCkgc2F0dXJhdGUoMTgwJSk7XG4gICAgICBib3JkZXItdG9wOiB2YXIoLS1ib3JkZXItc2l6ZS0xKSBzb2xpZCB2YXIoLS1ib3JkZXIpO1xuICAgICAgcGFkZGluZzogMCBlbnYoc2FmZS1hcmVhLWluc2V0LXJpZ2h0KSAwIGVudihzYWZlLWFyZWEtaW5zZXQtbGVmdCk7XG4gICAgICBwYWRkaW5nLWJvdHRvbTogZW52KHNhZmUtYXJlYS1pbnNldC1ib3R0b20pO1xuICAgIH1cbiAgICAudGFiLWl0ZW0ge1xuICAgICAgZmxleDogMTsgZGlzcGxheTogZmxleDsgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7IGp1c3RpZnktY29udGVudDogY2VudGVyOyBnYXA6IDJweDtcbiAgICAgIGNvbG9yOiB2YXIoLS10ZXh0LW11dGVkKTtcbiAgICAgIHRleHQtZGVjb3JhdGlvbjogbm9uZTsgZm9udC1zaXplOiAxMHB4OyBmb250LXdlaWdodDogNjAwO1xuICAgICAgdHJhbnNpdGlvbjogY29sb3IgMC4xNXMgZWFzZTtcbiAgICAgIC13ZWJraXQtdGFwLWhpZ2hsaWdodC1jb2xvcjogdHJhbnNwYXJlbnQ7IHBhZGRpbmc6IDRweCAwO1xuICAgIH1cbiAgICAudGFiLWl0ZW0gc3ZnIHsgd2lkdGg6IDIwcHg7IGhlaWdodDogMjBweDsgZmxleC1zaHJpbms6IDA7IH1cbiAgICAudGFiLWl0ZW06aG92ZXIgeyBjb2xvcjogdmFyKC0tdGV4dC1zZWNvbmRhcnkpOyB9XG4gICAgLnRhYi1pdGVtLmFjdGl2ZSB7IGNvbG9yOiB2YXIoLS1icmFuZCk7IH1cbiAgfVxuXG4gIEBtZWRpYSAobWF4LXdpZHRoOiA3NjhweCkge1xuICAgIC5oZWFkZXItcmlnaHQgeyBnYXA6IDRweDsgfVxuICAgIC5sYW5nLXN3aXRjaCB7IGRpc3BsYXk6IG5vbmU7IH1cbiAgfVxuICBAbWVkaWEgKG1heC13aWR0aDogNDgwcHgpIHtcbiAgICAuYnRuLXByaW1hcnkgeyBkaXNwbGF5OiBub25lOyB9XG4gICAgLmJ0bi1zZWNvbmRhcnkgeyBwYWRkaW5nOiA4cHg7IGJvcmRlcjogbm9uZTsgfVxuICAgIC5idG4tc2Vjb25kYXJ5IC5idG4tdGV4dCB7IGRpc3BsYXk6IG5vbmU7IH1cbiAgICAuaGVhZGVyLWlubmVyIHsgcGFkZGluZzogMCB2YXIoLS1zaXplLTMpOyBnYXA6IHZhcigtLXNpemUtMSk7IH1cbiAgfVxuYCk7XG5cbmV4cG9ydCBjbGFzcyBPcGVuTGF5b3V0IGV4dGVuZHMgT3BlbkVsZW1lbnQge1xuICBwcml2YXRlIF9jbGVhbnVwTmF2PzogKCkgPT4gdm9pZDtcbiAgcHJpdmF0ZSBfc2Nyb2xsQ2xlYW51cD86ICgpID0+IHZvaWQ7XG4gIHByaXZhdGUgX25hdk9wdGlvbnM/OiB7XG4gICAgY29udGVudExvYWRlcjogKHBhdGg6IHN0cmluZywgbG9jYWxlOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD47XG4gICAgb25BZnRlclN3YXA/OiAocGF0aDogc3RyaW5nLCBsb2NhbGU6IHN0cmluZykgPT4gdm9pZDtcbiAgfTtcblxuICBwcml2YXRlIGdldCBfbG9jYWxlcygpOiBzdHJpbmdbXSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJhdyA9ICh0aGlzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KS5sb2NhbGVzIHx8IHRoaXMuZ2V0QXR0cmlidXRlKCdsb2NhbGVzJyk7XG4gICAgICBpZiAocmF3KSB7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJhdykpIHJldHVybiByYXcgYXMgc3RyaW5nW107XG4gICAgICAgIGlmICh0eXBlb2YgcmF3ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShyYXcpO1xuICAgICAgICAgIH0gY2F0Y2ggeyAvKiBpZ25vcmUgKi8gfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gWydlbiddO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIFsnZW4nXTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldCBfZGVmYXVsdExvY2FsZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmdldEF0dHJpYnV0ZSgnbG9jYWxlJykgfHwgdGhpcy5fbG9jYWxlc1swXSB8fCAnZW4nO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgX2N1cnJlbnRMb2NhbGUoKTogc3RyaW5nIHtcbiAgICB0cnkge1xuICAgICAgaWYgKHR5cGVvZiBnbG9iYWxUaGlzLmxvY2F0aW9uICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICByZXR1cm4gZGV0ZWN0TG9jYWxlKGxvY2F0aW9uLnBhdGhuYW1lLCB0aGlzLl9sb2NhbGVzLCB0aGlzLl9kZWZhdWx0TG9jYWxlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLl9kZWZhdWx0TG9jYWxlO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIHRoaXMuX2RlZmF1bHRMb2NhbGU7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXQgX2N1cnJlbnRQYXRoV2l0aG91dExvY2FsZSgpOiBzdHJpbmcge1xuICAgIHRyeSB7XG4gICAgICBpZiAodHlwZW9mIGdsb2JhbFRoaXMubG9jYXRpb24gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybiBwYXJzZVBhdGhXaXRob3V0TG9jYWxlKGxvY2F0aW9uLnBhdGhuYW1lLCB0aGlzLl9sb2NhbGVzKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLmdldEF0dHJpYnV0ZSgnY3VycmVudC1wYXRoJykgfHwgJy8nO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuICcvJztcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgb3ZlcnJpZGUgc3R5bGVzID0gW3NoZWV0XTtcbiAgc3RhdGljIG92ZXJyaWRlIG9ic2VydmVkQXR0cmlidXRlcyA9IFtcbiAgICAnY3VycmVudC1wYXRoJyxcbiAgICAnbmF2LWl0ZW1zJyxcbiAgICAnaGVhZGVyLW5hdicsXG4gICAgJ2xvZ28tdGV4dCcsXG4gICAgJ2xvZ28tc3ViJyxcbiAgICAnZ2l0aHViLXVybCcsXG4gICAgJ2VkaXQtdXJsJyxcbiAgICAnbG9jYWxlJyxcbiAgICAnbG9jYWxlcycsXG4gIF07XG5cbiAgcHJpdmF0ZSBfdGhlbWVIYW5kbGVyPzogKGU6IEV2ZW50KSA9PiB2b2lkO1xuICBwcml2YXRlIF9kb2NDbGlja0NsZWFudXA/OiAoKSA9PiB2b2lkO1xuXG4gIG92ZXJyaWRlIHJlbmRlcigpOiBSZXR1cm5UeXBlPHR5cGVvZiBPcGVuRWxlbWVudC5wcm90b3R5cGUucmVuZGVyPiB7XG4gICAgcmV0dXJuIHRoaXMuX3JlbmRlckxheW91dCgpO1xuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0U3RyKGF0dHI6IHN0cmluZywgZGVmOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGNhbWVsID0gYXR0ci5yZXBsYWNlKC8tKFthLXpdKS9nLCAoXywgYzogc3RyaW5nKSA9PiBjLnRvVXBwZXJDYXNlKCkpO1xuICAgIGNvbnN0IHByb3AgPSAodGhpcyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPilbY2FtZWxdO1xuICAgIGlmIChwcm9wICE9PSB1bmRlZmluZWQgJiYgcHJvcCAhPT0gbnVsbCkgcmV0dXJuIFN0cmluZyhwcm9wKTtcbiAgICByZXR1cm4gdGhpcy5nZXRBdHRyaWJ1dGUoYXR0cikgfHwgZGVmO1xuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0Qm9vbChhdHRyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBjYW1lbCA9IGF0dHIucmVwbGFjZSgvLShbYS16XSkvZywgKF8sIGM6IHN0cmluZykgPT4gYy50b1VwcGVyQ2FzZSgpKTtcbiAgICBjb25zdCBwcm9wID0gKHRoaXMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW2NhbWVsXTtcbiAgICBpZiAodHlwZW9mIHByb3AgPT09ICdib29sZWFuJykgcmV0dXJuIHByb3A7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKGF0dHIpO1xuICB9XG5cbiAgLy8gX2N1cnJlbnRQYXRoV2l0aG91dExvY2FsZSwgX2N1cnJlbnRMb2NhbGUsIF9sb2NhbGVzLCBfc3dpdGNoUGF0aCgpLFxuICAvLyBfc3dpdGNoTGFiZWwoKSwgX3VwZGF0ZVN3aXRjaCgpLCBfbG9jYWxpemVQYXRoKClcbiAgLy8gPz8gYWxsIGlubGluZWQgKHJlcGxhY2VzIGZvcm1lciBAb3BlbmVsZW1lbnQvcm91dGVyIGRlcGVuZGVuY3kpXG5cbiAgcHJpdmF0ZSBfY3VycmVudFBhdGgoKTogc3RyaW5nIHtcbiAgICAvLyBTU1Itc2FmZTogcHJlZmVyIGF0dHJpYnV0ZS9wcm9wIHNldCBieSByZW5kZXJEc2Qgb3ZlciBVUkwgZGV0ZWN0aW9uXG4gICAgLy8gbG9jYXRpb24ucGF0aG5hbWUgaXMgdW5kZWZpbmVkIGR1cmluZyBidWlsZC5cbiAgICBjb25zdCBwcm9wID0gKHRoaXMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pLmN1cnJlbnRQYXRoO1xuICAgIGlmICh0eXBlb2YgcHJvcCA9PT0gJ3N0cmluZycgJiYgcHJvcC5sZW5ndGggPiAwKSByZXR1cm4gcHJvcDtcbiAgICBjb25zdCBhdHRyID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ2N1cnJlbnQtcGF0aCcpO1xuICAgIGlmIChhdHRyICYmIGF0dHIubGVuZ3RoID4gMCkgcmV0dXJuIGF0dHI7XG4gICAgdHJ5IHtcbiAgICAgIGlmICh0eXBlb2YgZ2xvYmFsVGhpcy5sb2NhdGlvbiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlUGF0aFdpdGhvdXRMb2NhbGUobG9jYXRpb24ucGF0aG5hbWUsIHRoaXMuX2xvY2FsZXMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMuZ2V0QXR0cmlidXRlKCdjdXJyZW50LXBhdGgnKSB8fCAnLyc7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gJy8nO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBDb21wdXRlIEdpdEh1YiBlZGl0IFVSTCBmcm9tIGN1cnJlbnQgcGF0aC4gKi9cbiAgcHJpdmF0ZSBfY29tcHV0ZUVkaXRVcmwoKTogc3RyaW5nIHtcbiAgICBjb25zdCBwYXRoID0gdGhpcy5fY3VycmVudFBhdGgoKTtcbiAgICBpZiAoIXBhdGggfHwgcGF0aCA9PT0gJy8nKSByZXR1cm4gJyc7XG4gICAgY29uc3QgRURJVF9CQVNFID0gJ2h0dHBzOi8vZ2l0aHViLmNvbS9vcGVuLWVsZW1lbnQvb3BlbmVsZW1lbnQvZWRpdC9tYWluL3d3dy9hcHAvcm91dGVzJztcbiAgICBjb25zdCBjbGVhbiA9IHBhdGgucmVwbGFjZSgvXFwvJC8sICcnKS5zcGxpdCgnLycpLmZpbHRlcihCb29sZWFuKTtcbiAgICAvLyBSZW1vdmUgbG9jYWxlIHByZWZpeCBpZiBwcmVzZW50IChlbi8sIHpoLylcbiAgICBpZiAoWydlbicsICd6aCddLmluY2x1ZGVzKGNsZWFuWzBdKSkgY2xlYW4uc2hpZnQoKTtcbiAgICBjb25zdCBmaWxlUGF0aCA9IGNsZWFuLmxlbmd0aCA9PT0gMCA/ICdpbmRleC9pbmRleCcgOiBjbGVhbi5qb2luKCcvJyk7XG4gICAgcmV0dXJuIGAke0VESVRfQkFTRX0vJHtmaWxlUGF0aH0udHN4YDtcbiAgfVxuXG4gIHByaXZhdGUgX25hdkl0ZW1zKCk6IE5hdlNlY3Rpb25bXSB7XG4gICAgY29uc3QgaXRlbXMgPSB0aGlzLl9yYXdOYXZJdGVtcygpO1xuICAgIHJldHVybiB0aGlzLl9maWx0ZXJCeVBhdGgoaXRlbXMpO1xuICB9XG5cbiAgLyoqIEF1dG8tZmlsdGVyIHNpZGViYXIgc2VjdGlvbnMgYnkgY3VycmVudCBwYXRoIHByZWZpeC4gKi9cbiAgcHJpdmF0ZSBfZmlsdGVyQnlQYXRoKGl0ZW1zOiBOYXZTZWN0aW9uW10pOiBOYXZTZWN0aW9uW10ge1xuICAgIGNvbnN0IHBhdGggPSB0aGlzLl9jdXJyZW50UGF0aCgpO1xuICAgIGNvbnN0IFNFQ1RJT05fTUFQOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT4gPSB7XG4gICAgICAnL2d1aWRlJzogWydRdWljayBTdGFydCcsICdDb3JlJywgJ1Byb2R1Y3Rpb24nXSxcbiAgICAgICcvYXJjaGl0ZWN0dXJlJzogWydQcmluY2lwbGVzJywgJ0NvbXBhdGliaWxpdHknLCAnUmVmZXJlbmNlJ10sXG4gICAgICAnL3JlZ2lzdHJ5JzogWydSZWdpc3RyeSddLFxuICAgICAgJy9odWInOiBbJ1JlZ2lzdHJ5J10sXG4gICAgICAnL2Jsb2cnOiBbJ0hpc3RvcnknXSxcbiAgICB9O1xuICAgIGZvciAoY29uc3QgW3ByZWZpeCwgc2VjdGlvbnNdIG9mIE9iamVjdC5lbnRyaWVzKFNFQ1RJT05fTUFQKSkge1xuICAgICAgaWYgKHBhdGguc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICAgIHJldHVybiBpdGVtcy5maWx0ZXIoKHMpID0+IHNlY3Rpb25zLmluY2x1ZGVzKHMuc2VjdGlvbikpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaXRlbXM7XG4gIH1cblxuICBwcml2YXRlIF9yYXdOYXZJdGVtcygpOiBOYXZTZWN0aW9uW10ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBwcm9wID0gKHRoaXMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pLm5hdkl0ZW1zO1xuICAgICAgaWYgKHByb3AgJiYgQXJyYXkuaXNBcnJheShwcm9wKSkgcmV0dXJuIHByb3AgYXMgTmF2U2VjdGlvbltdO1xuICAgICAgY29uc3QgcmF3ID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ25hdi1pdGVtcycpO1xuICAgICAgaWYgKHJhdykgcmV0dXJuIEpTT04ucGFyc2UocmF3KTtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsb2cud2FybignRmFpbGVkIHRvIHBhcnNlIG5hdi1pdGVtcyBKU09OOicsIGUpO1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2hlYWRlck5hdigpOiBIZWFkZXJOYXZMaW5rW10ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBwcm9wID0gKHRoaXMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pLmhlYWRlck5hdjtcbiAgICAgIGlmIChwcm9wICYmIEFycmF5LmlzQXJyYXkocHJvcCkpIHJldHVybiBwcm9wIGFzIEhlYWRlck5hdkxpbmtbXTtcbiAgICAgIGNvbnN0IHJhdyA9IHRoaXMuZ2V0QXR0cmlidXRlKCdoZWFkZXItbmF2Jyk7XG4gICAgICBpZiAocmF3KSByZXR1cm4gSlNPTi5wYXJzZShyYXcpO1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZy53YXJuKCdGYWlsZWQgdG8gcGFyc2UgaGVhZGVyLW5hdiBKU09OOicsIGUpO1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgfVxuXG4gIC8vIC0tLSBJY29ucyAtLS1cblxuICAvKiogdjAuMjQuMTogU1ZHIGljb24gYXR0cmlidXRlcyBzaGFyZWQgYWNyb3NzIGFsbCBtb2JpbGUgdGFiIGJhciBpY29ucy4gKi9cbiAgcHJpdmF0ZSBzdGF0aWMgX0lDT05fQVRUUlMgPSB7XG4gICAgdmlld0JveDogJzAgMCAyMCAyMCcsXG4gICAgZmlsbDogJ25vbmUnLFxuICAgIHN0cm9rZTogJ2N1cnJlbnRDb2xvcicsXG4gICAgJ3N0cm9rZS13aWR0aCc6ICcxLjUnLFxuICAgICdzdHJva2UtbGluZWNhcCc6ICdyb3VuZCcgYXMgY29uc3QsXG4gICAgJ3N0cm9rZS1saW5lam9pbic6ICdyb3VuZCcgYXMgY29uc3QsXG4gIH07XG5cbiAgLyoqIHYwLjI0LjE6IFJlbmRlciBtb2JpbGUgdGFiIGljb24gYXMgSlNYIFNWRy4gRmFsbHMgYmFjayB0byBhIGdlbmVyaWMgc2hhcGUuICovXG4gIHByaXZhdGUgX3JlbmRlckljb24obGFiZWw6IHN0cmluZykge1xuICAgIGNvbnN0IGEgPSBPcGVuTGF5b3V0Ll9JQ09OX0FUVFJTO1xuICAgIHN3aXRjaCAobGFiZWwpIHtcbiAgICAgIGNhc2UgJ0hvbWUnOlxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIDxzdmcgey4uLmF9PlxuICAgICAgICAgICAgPHBhdGggZD0nTTMgMTBsNy03IDcgNycgLz5cbiAgICAgICAgICAgIDxwYXRoIGQ9J001IDh2OWgzdi01aDR2NWgzVjgnIC8+XG4gICAgICAgICAgPC9zdmc+XG4gICAgICAgICk7XG4gICAgICBjYXNlICdEb2NzJzpcbiAgICAgIGNhc2UgJ0Jsb2cnOlxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIDxzdmcgey4uLmF9PlxuICAgICAgICAgICAgPHJlY3QgeD0nMycgeT0nMicgd2lkdGg9JzE0JyBoZWlnaHQ9JzE2JyByeD0nMicgLz5cbiAgICAgICAgICAgIDxwYXRoIGQ9J003IDZoNk03IDEwaDZNNyAxNGgzJyAvPlxuICAgICAgICAgIDwvc3ZnPlxuICAgICAgICApO1xuICAgICAgY2FzZSAnRXhhbXBsZXMnOlxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIDxzdmcgey4uLmF9PlxuICAgICAgICAgICAgPHJlY3QgeD0nMycgeT0nMycgd2lkdGg9JzE0JyBoZWlnaHQ9JzE0JyByeD0nMicgLz5cbiAgICAgICAgICAgIDxwYXRoIGQ9J003IDdsNiAzLTYgM3onIC8+XG4gICAgICAgICAgPC9zdmc+XG4gICAgICAgICk7XG4gICAgICBjYXNlICdDb21wb25lbnRzJzpcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICA8c3ZnIHsuLi5hfT5cbiAgICAgICAgICAgIDxyZWN0IHg9JzInIHk9JzInIHdpZHRoPSc3JyBoZWlnaHQ9JzcnIHJ4PScxJyAvPlxuICAgICAgICAgICAgPHJlY3QgeD0nMTEnIHk9JzInIHdpZHRoPSc3JyBoZWlnaHQ9JzcnIHJ4PScxJyAvPlxuICAgICAgICAgICAgPHJlY3QgeD0nMicgeT0nMTEnIHdpZHRoPSc3JyBoZWlnaHQ9JzcnIHJ4PScxJyAvPlxuICAgICAgICAgICAgPHJlY3QgeD0nMTEnIHk9JzExJyB3aWR0aD0nNycgaGVpZ2h0PSc3JyByeD0nMScgLz5cbiAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgKTtcbiAgICAgIGNhc2UgJ0FyY2hpdGVjdHVyZSc6XG4gICAgICBjYXNlICdFbmdpbmUnOlxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIDxzdmcgey4uLmF9PlxuICAgICAgICAgICAgPGNpcmNsZSBjeD0nMTAnIGN5PScxMCcgcj0nMycgLz5cbiAgICAgICAgICAgIDxwYXRoIGQ9J00xMCAxdjJNMTAgMTd2Mk0zLjUgMy41bDEuNCAxLjRNMTUuMSAxNS4xbDEuNCAxLjRNMSAxMGgyTTE3IDEwaDJNMy41IDE2LjVsMS40LTEuNE0xNS4xIDQuOWwxLjQtMS40JyAvPlxuICAgICAgICAgIDwvc3ZnPlxuICAgICAgICApO1xuICAgICAgY2FzZSAnSHViJzpcbiAgICAgIGNhc2UgJ1JlZ2lzdHJ5SHViJzpcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICA8c3ZnIHsuLi5hfT5cbiAgICAgICAgICAgIDxwYXRoIGQ9J00xMCAybDcgNHY4bC03IDQtNy00VjZ6JyAvPlxuICAgICAgICAgICAgPHBhdGggZD0nTTEwIDEwbDctNE0xMCAxMHY4TTEwIDEwTDMgNicgLz5cbiAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgKTtcbiAgICAgIGNhc2UgJ1JvYWRtYXAnOlxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIDxzdmcgey4uLmF9PlxuICAgICAgICAgICAgPGNpcmNsZSBjeD0nNCcgY3k9JzYnIHI9JzEuNScgLz5cbiAgICAgICAgICAgIDxjaXJjbGUgY3g9JzEwJyBjeT0nMTAnIHI9JzEuNScgLz5cbiAgICAgICAgICAgIDxjaXJjbGUgY3g9JzE2JyBjeT0nMTQnIHI9JzEuNScgLz5cbiAgICAgICAgICAgIDxwYXRoIGQ9J001LjUgNmgxME0xMS41IDEwaDUnIC8+XG4gICAgICAgICAgPC9zdmc+XG4gICAgICAgICk7XG4gICAgICBjYXNlICdGcmFtZXdvcmsnOlxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIDxzdmcgey4uLmF9PlxuICAgICAgICAgICAgPHBhdGggZD0nTTUgM2gxME01IDN2Nmg3TTEyIDl2M001IDE3aDcnIC8+XG4gICAgICAgICAgPC9zdmc+XG4gICAgICAgICk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIDxzdmcgey4uLmF9PlxuICAgICAgICAgICAgPGNpcmNsZSBjeD0nMTAnIGN5PScxMCcgcj0nOCcgLz5cbiAgICAgICAgICAgIDxwYXRoIGQ9J002IDZsMyA1IDUgMy0zLTV6JyAvPlxuICAgICAgICAgIDwvc3ZnPlxuICAgICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3NhZmVIcmVmKGhyZWY6IHN0cmluZyB8IHVuZGVmaW5lZCwgZmFsbGJhY2sgPSAnIycpOiBzdHJpbmcge1xuICAgIGlmICghaHJlZikgcmV0dXJuIGZhbGxiYWNrO1xuICAgIGNvbnN0IHRyaW1tZWQgPSBocmVmLnRyaW0oKTtcbiAgICByZXR1cm4gaXNTYWZlTGF5b3V0VXJsKHRyaW1tZWQpID8gdHJpbW1lZCA6IGZhbGxiYWNrO1xuICB9XG5cbiAgcHJpdmF0ZSBfaXNFeHRlcm5hbEhyZWYoaHJlZjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IG5ldyBVUkwoaHJlZiwgJ2h0dHBzOi8vb3BlbmVsZW1lbnQub3JnLycpO1xuICAgICAgcmV0dXJuIHBhcnNlZC5vcmlnaW4gIT09ICdodHRwczovL29wZW5lbGVtZW50Lm9yZycgJiYgU0FGRV9VUkxfU0NIRU1FUy5oYXMocGFyc2VkLnByb3RvY29sKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9sb2NhbGl6ZWRTYWZlSHJlZihocmVmOiBzdHJpbmcgfCB1bmRlZmluZWQpOiB7IGhyZWY6IHN0cmluZzsgaXNFeHRlcm5hbDogYm9vbGVhbiB9IHtcbiAgICBjb25zdCBzYWZlSHJlZiA9IHRoaXMuX3NhZmVIcmVmKGhyZWYpO1xuICAgIGNvbnN0IGlzRXh0ZXJuYWwgPSB0aGlzLl9pc0V4dGVybmFsSHJlZihzYWZlSHJlZik7XG4gICAgcmV0dXJuIHtcbiAgICAgIGhyZWY6IGlzRXh0ZXJuYWwgPyBzYWZlSHJlZiA6IGxvY2FsaXplUGF0aChzYWZlSHJlZiwgdGhpcy5fY3VycmVudExvY2FsZSksXG4gICAgICBpc0V4dGVybmFsLFxuICAgIH07XG4gIH1cblxuICAvLyAtLS0gTWFpbiByZW5kZXIgLS0tXG5cbiAgcHJpdmF0ZSBfcmVuZGVyTGF5b3V0KCkge1xuICAgIGNvbnN0IGhvbWUgPSB0aGlzLl9nZXRCb29sKCdmdWxsLXdpZHRoJykgfHwgdGhpcy5fZ2V0Qm9vbCgnaG9tZScpO1xuICAgIGNvbnN0IG5vU2VhcmNoID0gdGhpcy5oYXNBdHRyaWJ1dGUoJ25vLXNlYXJjaCcpO1xuICAgIGNvbnN0IGxvZ29UZXh0ID0gdGhpcy5fZ2V0U3RyKCdsb2dvLXRleHQnLCAnJyk7XG4gICAgY29uc3QgbG9nb1N1YiA9IHRoaXMuX2dldFN0cignbG9nby1zdWInLCAnJyk7XG4gICAgY29uc3QgbG9jYWxlcyA9IHRoaXMuX2xvY2FsZXM7XG4gICAgY29uc3QgY3VycmVudExvY2FsZSA9IHRoaXMuX2N1cnJlbnRMb2NhbGU7XG4gICAgY29uc3QgY3VycmVudFBhdGggPSB0aGlzLl9jdXJyZW50UGF0aFdpdGhvdXRMb2NhbGU7XG4gICAgY29uc3QgbGFuZ0xhYmVsID0gbG9jYWxlcy5sZW5ndGggPiAxID8gc3dpdGNoTGFiZWwoY3VycmVudExvY2FsZSkgOiAnJztcbiAgICBjb25zdCBsYW5nSHJlZiA9IGxvY2FsZXMubGVuZ3RoID4gMSA/IHN3aXRjaFBhdGgoY3VycmVudFBhdGgsIGN1cnJlbnRMb2NhbGUsIGxvY2FsZXMpIDogJyc7XG5cbiAgICByZXR1cm4gKFxuICAgICAgPGRpdiBjbGFzc05hbWU9J2FwcC1sYXlvdXQnIHBhcnQ9J2NvbnRhaW5lcicgaG9tZT17aG9tZSB8fCB1bmRlZmluZWR9PlxuICAgICAgICA8aGVhZGVyIGNsYXNzTmFtZT0nYXBwLWhlYWRlcicgcGFydD0naGVhZGVyJz5cbiAgICAgICAgICA8bmF2IGNsYXNzTmFtZT0naGVhZGVyLWlubmVyJyBhcmlhLWxhYmVsPSdQcmltYXJ5IG5hdmlnYXRpb24nPlxuICAgICAgICAgICAgeyhsb2dvVGV4dCB8fCBsb2dvU3ViKSAmJiAoXG4gICAgICAgICAgICAgIDxhIGNsYXNzTmFtZT0nbG9nbycgaHJlZj0nLyc+XG4gICAgICAgICAgICAgICAgPG9wZW4tYnJhbmQtbWFyayBzaXplPSdtZCc+PC9vcGVuLWJyYW5kLW1hcms+XG4gICAgICAgICAgICAgICAge2xvZ29UZXh0ICYmIDxzcGFuIGNsYXNzTmFtZT0nbG9nby13b3JkJz57bG9nb1RleHR9PC9zcGFuPn1cbiAgICAgICAgICAgICAgICB7bG9nb1N1YiAmJiA8c3BhbiBjbGFzc05hbWU9J2xvZ28tc3ViJz57bG9nb1N1Yn08L3NwYW4+fVxuICAgICAgICAgICAgICA8L2E+XG4gICAgICAgICAgICApfVxuICAgICAgICAgICAge3RoaXMuX3JlbmRlckhlYWRlck5hdigpfVxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9J2hlYWRlci1yaWdodCc+XG4gICAgICAgICAgICAgIHshbm9TZWFyY2ggJiYgPG9wZW4tc2VhcmNoPjwvb3Blbi1zZWFyY2g+fVxuICAgICAgICAgICAgICB7IWhvbWUgJiYgKFxuICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgIHR5cGU9J2J1dHRvbidcbiAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT0nbW9iaWxlLW1lbnUtYnRuJ1xuICAgICAgICAgICAgICAgICAgcGFydD0nbmF2LXRvZ2dsZSdcbiAgICAgICAgICAgICAgICAgIGFyaWEtbGFiZWw9J1RvZ2dsZSBuYXZpZ2F0aW9uJ1xuICAgICAgICAgICAgICAgICAgb25DbGljaz17KGV2ZW50OiBFdmVudCkgPT4gdGhpcy5fdG9nZ2xlTWVudShldmVudCl9XG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgPHN2Z1xuICAgICAgICAgICAgICAgICAgICB3aWR0aD0nMTgnXG4gICAgICAgICAgICAgICAgICAgIGhlaWdodD0nMTgnXG4gICAgICAgICAgICAgICAgICAgIHZpZXdCb3g9JzAgMCAxOCAxOCdcbiAgICAgICAgICAgICAgICAgICAgZmlsbD0nbm9uZSdcbiAgICAgICAgICAgICAgICAgICAgc3Ryb2tlPSdjdXJyZW50Q29sb3InXG4gICAgICAgICAgICAgICAgICAgIHN0cm9rZS13aWR0aD0nMS41J1xuICAgICAgICAgICAgICAgICAgICBzdHJva2UtbGluZWNhcD0ncm91bmQnXG4gICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIDxsaW5lIHgxPSczJyB5MT0nNC41JyB4Mj0nMTUnIHkyPSc0LjUnIC8+XG4gICAgICAgICAgICAgICAgICAgIDxsaW5lIHgxPSczJyB5MT0nOScgeDI9JzE1JyB5Mj0nOScgLz5cbiAgICAgICAgICAgICAgICAgICAgPGxpbmUgeDE9JzMnIHkxPScxMy41JyB4Mj0nMTUnIHkyPScxMy41JyAvPlxuICAgICAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICl9XG4gICAgICAgICAgICAgIDxvcGVuLXRoZW1lLXRvZ2dsZT48L29wZW4tdGhlbWUtdG9nZ2xlPlxuICAgICAgICAgICAgICB7bG9jYWxlcy5sZW5ndGggPiAxICYmIChcbiAgICAgICAgICAgICAgICA8YVxuICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPSdsYW5nLXN3aXRjaCdcbiAgICAgICAgICAgICAgICAgIGhyZWY9e2xhbmdIcmVmfVxuICAgICAgICAgICAgICAgICAgZGF0YS1uYXY9e2xhbmdIcmVmfVxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgIHtsYW5nTGFiZWx9XG4gICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9uYXY+XG4gICAgICAgIDwvaGVhZGVyPlxuICAgICAgICA8ZGl2IGNsYXNzTmFtZT0nbW9iaWxlLWJhY2tkcm9wJz48L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzc05hbWU9J2xheW91dC1ib2R5Jz5cbiAgICAgICAgICB7IWhvbWUgJiYgdGhpcy5fcmVuZGVyU2lkZWJhck5hdigpfVxuICAgICAgICAgIDxtYWluIGNsYXNzTmFtZT0nbGF5b3V0LW1haW4nIHBhcnQ9J21haW4nPlxuICAgICAgICAgICAgPHNsb3Q+PC9zbG90PlxuICAgICAgICAgIDwvbWFpbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxmb290ZXIgY2xhc3NOYW1lPSdhcHAtZm9vdGVyJyBwYXJ0PSdmb290ZXInPlxuICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPSdmb290ZXItaW5uZXInPlxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9J2Zvb3Rlci1jb2x1bW4nPlxuICAgICAgICAgICAgICA8aDQ+UHJvZHVjdDwvaDQ+XG4gICAgICAgICAgICAgIDxhXG4gICAgICAgICAgICAgICAgaHJlZj17bG9jYWxpemVQYXRoKCcvZ3VpZGUvY29yZS1jb25jZXB0cycsIGN1cnJlbnRMb2NhbGUpfVxuICAgICAgICAgICAgICAgIGRhdGEtbmF2PXtsb2NhbGl6ZVBhdGgoJy9ndWlkZS9jb3JlLWNvbmNlcHRzJywgY3VycmVudExvY2FsZSl9XG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICBFbGVtZW50c1xuICAgICAgICAgICAgICA8L2E+XG4gICAgICAgICAgICAgIDxhXG4gICAgICAgICAgICAgICAgaHJlZj17bG9jYWxpemVQYXRoKCcvYXJjaGl0ZWN0dXJlL2Rlc2lnbi1zeXN0ZW0nLCBjdXJyZW50TG9jYWxlKX1cbiAgICAgICAgICAgICAgICBkYXRhLW5hdj17bG9jYWxpemVQYXRoKCcvYXJjaGl0ZWN0dXJlL2Rlc2lnbi1zeXN0ZW0nLCBjdXJyZW50TG9jYWxlKX1cbiAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIFVJXG4gICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgPGFcbiAgICAgICAgICAgICAgICBocmVmPXtsb2NhbGl6ZVBhdGgoJy9hcmNoaXRlY3R1cmUvYXJjaGl0ZWN0dXJlJywgY3VycmVudExvY2FsZSl9XG4gICAgICAgICAgICAgICAgZGF0YS1uYXY9e2xvY2FsaXplUGF0aCgnL2FyY2hpdGVjdHVyZS9hcmNoaXRlY3R1cmUnLCBjdXJyZW50TG9jYWxlKX1cbiAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIEZyYW1ld29ya1xuICAgICAgICAgICAgICA8L2E+XG4gICAgICAgICAgICAgIDxhXG4gICAgICAgICAgICAgICAgaHJlZj17bG9jYWxpemVQYXRoKCcvYXJjaGl0ZWN0dXJlL3N0YW5kYXJkcy1yZWdpc3RyeScsIGN1cnJlbnRMb2NhbGUpfVxuICAgICAgICAgICAgICAgIGRhdGEtbmF2PXtsb2NhbGl6ZVBhdGgoJy9hcmNoaXRlY3R1cmUvc3RhbmRhcmRzLXJlZ2lzdHJ5JywgY3VycmVudExvY2FsZSl9XG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICBQcm90b2NvbHNcbiAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT0nZm9vdGVyLWNvbHVtbic+XG4gICAgICAgICAgICAgIDxoND5SZXNvdXJjZXM8L2g0PlxuICAgICAgICAgICAgICA8YVxuICAgICAgICAgICAgICAgIGhyZWY9e2xvY2FsaXplUGF0aCgnL2d1aWRlL2dldHRpbmctc3RhcnRlZCcsIGN1cnJlbnRMb2NhbGUpfVxuICAgICAgICAgICAgICAgIGRhdGEtbmF2PXtsb2NhbGl6ZVBhdGgoJy9ndWlkZS9nZXR0aW5nLXN0YXJ0ZWQnLCBjdXJyZW50TG9jYWxlKX1cbiAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIEd1aWRlXG4gICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgPGFcbiAgICAgICAgICAgICAgICBocmVmPXtsb2NhbGl6ZVBhdGgoJy9ndWlkZS9hcGknLCBjdXJyZW50TG9jYWxlKX1cbiAgICAgICAgICAgICAgICBkYXRhLW5hdj17bG9jYWxpemVQYXRoKCcvZ3VpZGUvYXBpJywgY3VycmVudExvY2FsZSl9XG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICBBUElcbiAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICA8YVxuICAgICAgICAgICAgICAgIGhyZWY9e2xvY2FsaXplUGF0aCgnL2FyY2hpdGVjdHVyZS9hcmNoaXRlY3R1cmUnLCBjdXJyZW50TG9jYWxlKX1cbiAgICAgICAgICAgICAgICBkYXRhLW5hdj17bG9jYWxpemVQYXRoKCcvYXJjaGl0ZWN0dXJlL2FyY2hpdGVjdHVyZScsIGN1cnJlbnRMb2NhbGUpfVxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgQXJjaGl0ZWN0dXJlXG4gICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgPGFcbiAgICAgICAgICAgICAgICBocmVmPXtsb2NhbGl6ZVBhdGgoJy9ibG9nJywgY3VycmVudExvY2FsZSl9XG4gICAgICAgICAgICAgICAgZGF0YS1uYXY9e2xvY2FsaXplUGF0aCgnL2Jsb2cnLCBjdXJyZW50TG9jYWxlKX1cbiAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIEJsb2dcbiAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT0nZm9vdGVyLWNvbHVtbic+XG4gICAgICAgICAgICAgIDxoND5Db21wYW55PC9oND5cbiAgICAgICAgICAgICAgPGEgaHJlZj0naHR0cHM6Ly9naXRodWIuY29tL29wZW4tZWxlbWVudC9vcGVuZWxlbWVudCc+R2l0SHViPC9hPlxuICAgICAgICAgICAgICA8YVxuICAgICAgICAgICAgICAgIGhyZWY9e2xvY2FsaXplUGF0aCgnL3JvYWRtYXAnLCBjdXJyZW50TG9jYWxlKX1cbiAgICAgICAgICAgICAgICBkYXRhLW5hdj17bG9jYWxpemVQYXRoKCcvcm9hZG1hcCcsIGN1cnJlbnRMb2NhbGUpfVxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgUm9hZG1hcFxuICAgICAgICAgICAgICA8L2E+XG4gICAgICAgICAgICAgIDxhXG4gICAgICAgICAgICAgICAgaHJlZj17bG9jYWxpemVQYXRoKCcvY2hhbmdlbG9nJywgY3VycmVudExvY2FsZSl9XG4gICAgICAgICAgICAgICAgZGF0YS1uYXY9e2xvY2FsaXplUGF0aCgnL2NoYW5nZWxvZycsIGN1cnJlbnRMb2NhbGUpfVxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgQ2hhbmdlbG9nXG4gICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9J2Zvb3Rlci1jb2x1bW4nPlxuICAgICAgICAgICAgICA8aDQ+TGVnYWw8L2g0PlxuICAgICAgICAgICAgICA8YSBocmVmPSdodHRwczovL2dpdGh1Yi5jb20vb3Blbi1lbGVtZW50L29wZW5lbGVtZW50L2Jsb2IvbWFpbi9MSUNFTlNFJz5cbiAgICAgICAgICAgICAgICBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICA8L2E+XG4gICAgICAgICAgICAgIDxhXG4gICAgICAgICAgICAgICAgaHJlZj17bG9jYWxpemVQYXRoKCcvY29udHJpYnV0aW5nJywgY3VycmVudExvY2FsZSl9XG4gICAgICAgICAgICAgICAgZGF0YS1uYXY9e2xvY2FsaXplUGF0aCgnL2NvbnRyaWJ1dGluZycsIGN1cnJlbnRMb2NhbGUpfVxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgQ29udHJpYnV0aW5nXG4gICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPSdmb290ZXItYm90dG9tJz5cbiAgICAgICAgICAgIDxzcGFuPihjKSAyMDI2IG9wZW5FbGVtZW50LiBNSVQgTGljZW5zZS48L3NwYW4+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZm9vdGVyPlxuICAgICAgICB7dGhpcy5fcmVuZGVyTW9iaWxlVGFiQmFyKCl9XG4gICAgICA8L2Rpdj5cbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVuZGVySGVhZGVyTmF2KCkge1xuICAgIGNvbnN0IGxpbmtzID0gdGhpcy5faGVhZGVyTmF2KCk7XG4gICAgaWYgKGxpbmtzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgY3AgPSB0aGlzLl9jdXJyZW50UGF0aCgpO1xuICAgIHJldHVybiAoXG4gICAgICA8bmF2IGNsYXNzTmFtZT0naGVhZGVyLW5hdicgcGFydD0nbmF2Jz5cbiAgICAgICAge2xpbmtzLm1hcCgobGluaykgPT4ge1xuICAgICAgICAgIGNvbnN0IHsgaHJlZjogbG9jYWxpemVkLCBpc0V4dGVybmFsIH0gPSB0aGlzLl9sb2NhbGl6ZWRTYWZlSHJlZihsaW5rLmhyZWYpO1xuICAgICAgICAgIGNvbnN0IGlzQ3VycmVudCA9ICFpc0V4dGVybmFsICYmXG4gICAgICAgICAgICAoY3AgPT09IGxpbmsuaHJlZiB8fCBjcCA9PT0gbG9jYWxpemVkIHx8IGNwLnN0YXJ0c1dpdGgobG9jYWxpemVkICsgJy8nKSk7XG4gICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxhXG4gICAgICAgICAgICAgIGhyZWY9e2xvY2FsaXplZH1cbiAgICAgICAgICAgICAgZGF0YS1uYXY9e2lzRXh0ZXJuYWwgPyAnJyA6IGxvY2FsaXplZH1cbiAgICAgICAgICAgICAgYXJpYS1jdXJyZW50PXtpc0N1cnJlbnQgPyAncGFnZScgOiB1bmRlZmluZWR9XG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIHtsaW5rLmxhYmVsfVxuICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICk7XG4gICAgICAgIH0pfVxuICAgICAgPC9uYXY+XG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgX3JlbmRlclNpZGViYXJOYXYoKSB7XG4gICAgY29uc3QgbmF2ID0gdGhpcy5fbmF2SXRlbXMoKTtcbiAgICBpZiAobmF2Lmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIChcbiAgICAgIDxuYXZcbiAgICAgICAgY2xhc3NOYW1lPSdkb2NzLXNpZGViYXInXG4gICAgICAgIHBhcnQ9J3NpZGViYXInXG4gICAgICAgIGFyaWEtbGFiZWw9J0RvY3VtZW50YXRpb24gbmF2aWdhdGlvbidcbiAgICAgID5cbiAgICAgICAge25hdi5tYXAoKHNlY3Rpb24pID0+IChcbiAgICAgICAgICA8ZGV0YWlscyBjbGFzc05hbWU9J25hdi1zZWN0aW9uJyBvcGVuPlxuICAgICAgICAgICAgPHN1bW1hcnkgY2xhc3NOYW1lPSduYXYtc2VjdGlvbi10aXRsZSc+XG4gICAgICAgICAgICAgIHtzZWN0aW9uLnNlY3Rpb259XG4gICAgICAgICAgICA8L3N1bW1hcnk+XG4gICAgICAgICAgICB7c2VjdGlvbi5pdGVtcy5tYXAoKGl0ZW0pID0+IHtcbiAgICAgICAgICAgICAgY29uc3QgaHJlZiA9IGl0ZW0uaHJlZiB8fCBpdGVtLnBhdGggfHwgJyMnO1xuICAgICAgICAgICAgICBjb25zdCB7IGhyZWY6IGxvY2FsaXplZCwgaXNFeHRlcm5hbCB9ID0gdGhpcy5fbG9jYWxpemVkU2FmZUhyZWYoaHJlZik7XG4gICAgICAgICAgICAgIGNvbnN0IGNwID0gdGhpcy5fY3VycmVudFBhdGgoKTtcbiAgICAgICAgICAgICAgY29uc3QgaXNBY3RpdmUgPSAhaXNFeHRlcm5hbCAmJiBjcCA9PT0gbG9jYWxpemVkO1xuICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIDxhXG4gICAgICAgICAgICAgICAgICBocmVmPXtsb2NhbGl6ZWR9XG4gICAgICAgICAgICAgICAgICBjbGFzc05hbWU9e2lzQWN0aXZlID8gJ2FjdGl2ZScgOiB1bmRlZmluZWR9XG4gICAgICAgICAgICAgICAgICBhcmlhLWN1cnJlbnQ9e2lzQWN0aXZlID8gJ3BhZ2UnIDogdW5kZWZpbmVkfVxuICAgICAgICAgICAgICAgICAgZGF0YS1uYXY9e2lzRXh0ZXJuYWwgPyAnJyA6IGxvY2FsaXplZH1cbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICB7aXRlbS5sYWJlbH1cbiAgICAgICAgICAgICAgICA8L2E+XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KX1cbiAgICAgICAgICA8L2RldGFpbHM+XG4gICAgICAgICkpfVxuICAgICAgPC9uYXY+XG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgX3JlbmRlck1vYmlsZVRhYkJhcigpIHtcbiAgICBjb25zdCBsaW5rcyA9IHRoaXMuX2hlYWRlck5hdigpO1xuICAgIGlmIChsaW5rcy5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xuXG4gICAgY29uc3QgTU9CSUxFX1RBQl9MSU1JVCA9IDU7XG4gICAgY29uc3QgbW9iaWxlTGlua3MgPSBsaW5rcy5zbGljZSgwLCBNT0JJTEVfVEFCX0xJTUlUKTtcblxuICAgIGNvbnN0IGxvY3MgPSB0aGlzLl9sb2NhbGVzO1xuICAgIGNvbnN0IHNlY3Rpb25Sb290ID0gKGhyZWY6IHN0cmluZyk6IHN0cmluZyA9PiB7XG4gICAgICBjb25zdCBzZWdzID0gaHJlZi5zcGxpdCgnLycpLmZpbHRlcihCb29sZWFuKTtcbiAgICAgIGNvbnN0IHN0YXJ0ID0gbG9jcy5sZW5ndGggPiAxICYmIGxvY3MuaW5jbHVkZXMoc2Vnc1swXSkgPyAxIDogMDtcbiAgICAgIHJldHVybiBzZWdzLmxlbmd0aCA+IHN0YXJ0ICsgMSA/ICcvJyArIHNlZ3Nbc3RhcnRdIDogaHJlZjtcbiAgICB9O1xuXG4gICAgY29uc3QgcmF3UGF0aCA9IHRoaXMuX2N1cnJlbnRQYXRoV2l0aG91dExvY2FsZTtcblxuICAgIHJldHVybiAoXG4gICAgICA8bmF2IGNsYXNzTmFtZT0nbW9iaWxlLXRhYi1iYXInIGFyaWEtbGFiZWw9J1F1aWNrIG5hdmlnYXRpb24nPlxuICAgICAgICB7bW9iaWxlTGlua3MubWFwKChsaW5rKSA9PiB7XG4gICAgICAgICAgY29uc3QgeyBocmVmOiBsb2NhbGl6ZWQsIGlzRXh0ZXJuYWwgfSA9IHRoaXMuX2xvY2FsaXplZFNhZmVIcmVmKGxpbmsuaHJlZik7XG4gICAgICAgICAgY29uc3Qgcm9vdCA9IHNlY3Rpb25Sb290KGxpbmsuaHJlZik7XG4gICAgICAgICAgY29uc3QgaXNBY3RpdmUgPSAhaXNFeHRlcm5hbCAmJlxuICAgICAgICAgICAgKHJhd1BhdGggPT09IHJvb3QgfHwgcmF3UGF0aC5zdGFydHNXaXRoKHJvb3QgKyAnLycpKTtcbiAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgPGFcbiAgICAgICAgICAgICAgY2xhc3NOYW1lPXtgdGFiLWl0ZW0ke2lzQWN0aXZlID8gJyBhY3RpdmUnIDogJyd9YH1cbiAgICAgICAgICAgICAgaHJlZj17bG9jYWxpemVkfVxuICAgICAgICAgICAgICBkYXRhLW5hdj17aXNFeHRlcm5hbCA/ICcnIDogbG9jYWxpemVkfVxuICAgICAgICAgICAgICBhcmlhLWN1cnJlbnQ9e2lzQWN0aXZlID8gJ3BhZ2UnIDogdW5kZWZpbmVkfVxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICB7dGhpcy5fcmVuZGVySWNvbihsaW5rLmxhYmVsKX1cbiAgICAgICAgICAgICAgPHNwYW4+e2xpbmsubGFiZWx9PC9zcGFuPlxuICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICk7XG4gICAgICAgIH0pfVxuICAgICAgPC9uYXY+XG4gICAgKTtcbiAgfVxuXG4gIC8vIC0tLSBTY3JvbGwgZGV0ZWN0aW9uIC0tLVxuXG4gIHByaXZhdGUgX3NldHVwU2Nyb2xsRGV0ZWN0aW9uKCk6IHZvaWQge1xuICAgIGlmICh0eXBlb2YgZ2xvYmFsVGhpcy53aW5kb3cgPT09ICd1bmRlZmluZWQnKSByZXR1cm47XG4gICAgbGV0IHRpY2tpbmc6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+IHwgdW5kZWZpbmVkO1xuICAgIGNvbnN0IG9uU2Nyb2xsID0gKCkgPT4ge1xuICAgICAgaWYgKHRpY2tpbmcgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICAgICAgdGlja2luZyA9IGdsb2JhbFRoaXMuc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IGhlYWRlciA9IHRoaXMuc2hhZG93Um9vdD8ucXVlcnlTZWxlY3RvcignLmFwcC1oZWFkZXInKTtcbiAgICAgICAgaWYgKGhlYWRlcikge1xuICAgICAgICAgIGhlYWRlci5jbGFzc0xpc3QudG9nZ2xlKCdzY3JvbGxlZCcsIGdsb2JhbFRoaXMuc2Nyb2xsWSA+IDApO1xuICAgICAgICB9XG4gICAgICAgIHRpY2tpbmcgPSB1bmRlZmluZWQ7XG4gICAgICB9LCAxMDApO1xuICAgIH07XG4gICAgZ2xvYmFsVGhpcy5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBvblNjcm9sbCwgeyBwYXNzaXZlOiB0cnVlIH0pO1xuICAgIHRoaXMuX3Njcm9sbENsZWFudXAgPSAoKSA9PiB7XG4gICAgICBnbG9iYWxUaGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIG9uU2Nyb2xsKTtcbiAgICAgIGlmICh0aWNraW5nICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZ2xvYmFsVGhpcy5jbGVhclRpbWVvdXQodGlja2luZyk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgX3RlYXJkb3duU2Nyb2xsRGV0ZWN0aW9uKCk6IHZvaWQge1xuICAgIHRoaXMuX3Njcm9sbENsZWFudXA/LigpO1xuICAgIHRoaXMuX3Njcm9sbENsZWFudXAgPSB1bmRlZmluZWQ7XG4gIH1cblxuICAvLyAtLS0gTGlmZWN5Y2xlIC0tLVxuXG4gIG92ZXJyaWRlIGNvbm5lY3RlZENhbGxiYWNrKCk6IHZvaWQge1xuICAgIHN1cGVyLmNvbm5lY3RlZENhbGxiYWNrKCk7XG5cbiAgICBjb25zdCBsb2NhbGVzID0gdGhpcy5fbG9jYWxlcztcbiAgICBpZiAobG9jYWxlcy5sZW5ndGggPiAxKSB7XG4gICAgICBjb25zdCBsb2NhbGUgPSB0aGlzLl9jdXJyZW50TG9jYWxlO1xuICAgICAgaWYgKGxvY2FsZXMuaW5jbHVkZXMobG9jYWxlKSkge1xuICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZSgnbG9jYWxlJywgbG9jYWxlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTeW5jIGRhdGEtdGhlbWUgZnJvbSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgb24gY29ubmVjdFxuICAgIGNvbnN0IGRvY1RoZW1lID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50Py5kYXRhc2V0Py50aGVtZTtcbiAgICBpZiAoZG9jVGhlbWUpIHtcbiAgICAgIHRoaXMuc2V0QXR0cmlidXRlKCdkYXRhLXRoZW1lJywgZG9jVGhlbWUpO1xuICAgIH1cbiAgICAvLyBTaWduYWxDb250ZXh0OiBwcm92aWRlIHRoZW1lIHN0YXRlIHRvIGFsbCBjaGlsZCBjb21wb25lbnRzXG4gICAgY29uc3QgaW5pdGlhbFRoZW1lID0gKGRvY1RoZW1lIGFzICdkYXJrJyB8ICdsaWdodCcpIHx8ICdsaWdodCc7XG4gICAgcHJvdmlkZUNvbnRleHQodGhpcywgVEhFTUVfQ1RYLCBpbml0aWFsVGhlbWUpO1xuXG4gICAgLy8gTGlzdGVuIGZvciB0aGVtZSBjaGFuZ2UgZXZlbnRzIGZyb20gb3Blbi10aGVtZS10b2dnbGVcbiAgICB0aGlzLl90aGVtZUhhbmRsZXIgPSAoZTogRXZlbnQpID0+IHtcbiAgICAgIGNvbnN0IGRldGFpbCA9IChlIGFzIEN1c3RvbUV2ZW50KS5kZXRhaWw7XG4gICAgICBpZiAoZGV0YWlsPy50aGVtZSkge1xuICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZSgnZGF0YS10aGVtZScsIGRldGFpbC50aGVtZSk7XG4gICAgICAgIHByb3ZpZGVDb250ZXh0KHRoaXMsIFRIRU1FX0NUWCwgZGV0YWlsLnRoZW1lKTtcbiAgICAgICAgdGhpcy5fcHJvcGFnYXRlVGhlbWUoZGV0YWlsLnRoZW1lKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIGdsb2JhbFRoaXMuYWRkRXZlbnRMaXN0ZW5lcj8uKCdvcGVuOnRoZW1lLWNoYW5nZScsIHRoaXMuX3RoZW1lSGFuZGxlcik7XG5cbiAgICB0aGlzLl9wcm9wYWdhdGVUaGVtZShpbml0aWFsVGhlbWUpO1xuXG4gICAgaWYgKHRoaXMuc2hhZG93Um9vdCAmJiB0aGlzLnNoYWRvd1Jvb3QuY2hpbGROb2Rlcy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLl9zZXR1cERldGFpbHNUb2dnbGUoKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zZXR1cFNwYU5hdmlnYXRpb24oe1xuICAgICAgY29udGVudExvYWRlcjogYXN5bmMgKHBhdGg6IHN0cmluZywgbG9jYWxlOiBzdHJpbmcpID0+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5fbG9hZENvbnRlbnQocGF0aCwgbG9jYWxlKTtcbiAgICAgIH0sXG4gICAgICBvbkFmdGVyU3dhcDogKF9wYXRoOiBzdHJpbmcpID0+IHtcbiAgICAgICAgdGhpcy5fdXBkYXRlQWN0aXZlTmF2KCk7XG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8gdjAuMjMuMDogSW50ZWdyYXRlZCBmcm9tIHd3dy9wdWJsaWMvbW9iaWxlLW1lbnUuanMuXG4gICAgLy8gQ2xvc2UgbW9iaWxlIG1lbnUgb24gYmFja2Ryb3AgY2xpY2sgb3Igc2lkZWJhciBuYXYgbGluayBjbGljay5cbiAgICB0aGlzLl9kb2NDbGlja0NsZWFudXAgPSB0aGlzLl9zZXR1cEJhY2tkcm9wQ2xvc2UoKTtcblxuICAgIC8vIFNjcm9sbCBkZXRlY3Rpb24gZm9yIGhlYWRlciBiYWNrZHJvcCBibHVyXG4gICAgdGhpcy5fc2V0dXBTY3JvbGxEZXRlY3Rpb24oKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCk6IHZvaWQge1xuICAgIHN1cGVyLmRpc2Nvbm5lY3RlZENhbGxiYWNrKCk7XG4gICAgdGhpcy5fdGVhcmRvd25TcGFOYXZpZ2F0aW9uKCk7XG4gICAgdGhpcy5fZG9jQ2xpY2tDbGVhbnVwPy4oKTtcbiAgICBpZiAodGhpcy5fdGhlbWVIYW5kbGVyKSB7XG4gICAgICBnbG9iYWxUaGlzLnJlbW92ZUV2ZW50TGlzdGVuZXI/Lignb3Blbjp0aGVtZS1jaGFuZ2UnLCB0aGlzLl90aGVtZUhhbmRsZXIpO1xuICAgIH1cbiAgICB0aGlzLl90ZWFyZG93blNjcm9sbERldGVjdGlvbigpO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWU6IHN0cmluZywgb2xkOiBzdHJpbmcgfCBudWxsLCB2YWw6IHN0cmluZyB8IG51bGwpOiB2b2lkIHtcbiAgICBpZiAob2xkID09PSB2YWwpIHJldHVybjtcbiAgICBpZiAobmFtZSA9PT0gJ2N1cnJlbnQtcGF0aCcpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZUFjdGl2ZU5hdigpO1xuICAgIH1cbiAgfVxuXG4gIC8vIC0tLSBNb2JpbGUgbWVudSAtLS1cblxuICAvLyB2MC4zMSBVSS1zaGVsbCBkZWJ0OiByZXBsYWNlIF9yZXBsYWNlU2hhZG93Um9vdEZyb21MYXlvdXQgd2l0aCBzaWduYWwtZHJpdmVuIFNQQSBuYXYuXG4gIC8vIEN1cnJlbnRseSBTUEEgbmF2aWdhdGlvbiBkZXN0cm95cyB0aGUgZW50aXJlIHNoYWRvdyBET00gYW5kIHJlYnVpbGRzIGl0IGZyb21cbiAgLy8gZmV0Y2hlZCBIVE1MLCB0aGVuIG1hbnVhbGx5IHJlLWF0dGFjaGVzIGV2ZW50cyBpbiBfc2V0dXBEZXRhaWxzVG9nZ2xlLiBUaGlzIGlzXG4gIC8vIGluY29tcGF0aWJsZSB3aXRoIHRoZSBzaWduYWwgYXJjaGl0ZWN0dXJlID8/IHdlIHNob3VsZCBtYWtlIGN1cnJlbnRQYXRoL25hdkl0ZW1zXG4gIC8vIHNpZ25hbHMgYW5kIGxldCBkYXRhLXNpZ25hbCBtYXJrZXJzIGhhbmRsZSBET00gdXBkYXRlcyByZWFjdGl2ZWx5LiBUaGVuIHRoZVxuICAvLyBfc2V0dXBEZXRhaWxzVG9nZ2xlIGhhY2sgKGFuZCB0aGlzIGVudGlyZSBtZXRob2QpIGNhbiBiZSBkZWxldGVkLlxuICBwcml2YXRlIF9tZW51QnRuSGFuZGxlcjogKChlOiBFdmVudCkgPT4gdm9pZCkgfCBudWxsID0gbnVsbDtcblxuICBwcml2YXRlIF9zZXR1cERldGFpbHNUb2dnbGUoKTogdm9pZCB7XG4gICAgY29uc3QgYnRuID0gdGhpcy5zaGFkb3dSb290Py5xdWVyeVNlbGVjdG9yKCcubW9iaWxlLW1lbnUtYnRuJyk7XG4gICAgaWYgKCFidG4pIHJldHVybjtcbiAgICAvLyBSZW1vdmUgYW55IHN0YWxlIGxpc3RlbmVyIGZyb20gYSBwcmV2aW91cyBzaGFkb3cgcm9vdC5cbiAgICBpZiAodGhpcy5fbWVudUJ0bkhhbmRsZXIpIHtcbiAgICAgIGJ0bi5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX21lbnVCdG5IYW5kbGVyKTtcbiAgICB9XG4gICAgdGhpcy5fbWVudUJ0bkhhbmRsZXIgPSB0aGlzLl90b2dnbGVNZW51LmJpbmQodGhpcyk7XG4gICAgYnRuLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5fbWVudUJ0bkhhbmRsZXIpO1xuICB9XG5cbiAgcHJpdmF0ZSBfdG9nZ2xlTWVudShfZTogRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBpc09wZW4gPSB0aGlzLmhhc0F0dHJpYnV0ZSgnbWVudS1vcGVuJyk7XG4gICAgdGhpcy50b2dnbGVBdHRyaWJ1dGUoJ21lbnUtb3BlbicsICFpc09wZW4pO1xuICAgIHRoaXMuX3N5bmNJbmVydCghaXNPcGVuKTtcbiAgfVxuXG4gIHByaXZhdGUgX3N5bmNJbmVydChtZW51T3BlbjogYm9vbGVhbik6IHZvaWQge1xuICAgIGNvbnN0IG1haW4gPSB0aGlzLnNoYWRvd1Jvb3Q/LnF1ZXJ5U2VsZWN0b3IoJy5sYXlvdXQtbWFpbicpO1xuICAgIGlmIChtYWluKSB7XG4gICAgICBpZiAobWVudU9wZW4pIG1haW4uc2V0QXR0cmlidXRlKCdpbmVydCcsICcnKTtcbiAgICAgIGVsc2UgbWFpbi5yZW1vdmVBdHRyaWJ1dGUoJ2luZXJ0Jyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIHYwLjIzLjA6IEludGVncmF0ZWQgZnJvbSB3d3cvcHVibGljL21vYmlsZS1tZW51LmpzLlxuICAgKiBDbG9zZXMgbW9iaWxlIG1lbnUgd2hlbiBiYWNrZHJvcCBvciBzaWRlYmFyIG5hdiBsaW5rIGlzIGNsaWNrZWQuXG4gICAqIFVzZXMgY29tcG9zZWRQYXRoKCkgdG8gZGV0ZWN0IGNsaWNrcyBhY3Jvc3Mgc2hhZG93IERPTSBib3VuZGFyaWVzLlxuICAgKi9cbiAgcHJpdmF0ZSBfc2V0dXBCYWNrZHJvcENsb3NlKCk6ICgpID0+IHZvaWQge1xuICAgIGNvbnN0IGhhbmRsZXIgPSAoZTogRXZlbnQpID0+IHtcbiAgICAgIGNvbnN0IHRhcmdldCA9IGUudGFyZ2V0O1xuICAgICAgaWYgKCF0YXJnZXQgfHwgISh0YXJnZXQgaW5zdGFuY2VvZiBFbGVtZW50KSkgcmV0dXJuO1xuXG4gICAgICBjb25zdCBwYXRoID0gZS5jb21wb3NlZFBhdGgoKTtcbiAgICAgIGxldCBpc0JhY2tkcm9wID0gZmFsc2U7XG4gICAgICBsZXQgaXNOYXZMaW5rID0gZmFsc2U7XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGF0aC5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBlbCA9IHBhdGhbaV0gYXMgRWxlbWVudDtcbiAgICAgICAgaWYgKCFlbD8uY2xhc3NMaXN0KSBjb250aW51ZTtcbiAgICAgICAgaWYgKGVsLmNsYXNzTGlzdC5jb250YWlucygnbW9iaWxlLWJhY2tkcm9wJykpIHtcbiAgICAgICAgICBpc0JhY2tkcm9wID0gdHJ1ZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZiAoZWwudGFnTmFtZSA9PT0gJ0EnKSB7XG4gICAgICAgICAgaXNOYXZMaW5rID0gdHJ1ZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoIWlzQmFja2Ryb3AgJiYgIWlzTmF2TGluaykgcmV0dXJuO1xuICAgICAgdGhpcy5fY2xvc2VNZW51KCk7XG4gICAgfTtcblxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgaGFuZGxlcik7XG4gICAgcmV0dXJuICgpID0+IGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgaGFuZGxlcik7XG4gIH1cblxuICBwcml2YXRlIF9jbG9zZU1lbnUoKTogdm9pZCB7XG4gICAgdGhpcy5yZW1vdmVBdHRyaWJ1dGUoJ21lbnUtb3BlbicpO1xuICAgIGNvbnN0IGRldGFpbHMgPSB0aGlzLnNoYWRvd1Jvb3Q/LnF1ZXJ5U2VsZWN0b3IoJ2RldGFpbHMubW9iaWxlLW1lbnUnKTtcbiAgICBpZiAoZGV0YWlscykgZGV0YWlscy5yZW1vdmVBdHRyaWJ1dGUoJ29wZW4nKTtcbiAgICB0aGlzLl9zeW5jSW5lcnQoZmFsc2UpO1xuICB9XG5cbiAgLy8gLS0tIFRoZW1lIC0tLVxuICBwcml2YXRlIF9wcm9wYWdhdGVUaGVtZSh0aGVtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3Qgd2FsayA9IChyb290OiBFbGVtZW50IHwgU2hhZG93Um9vdCkgPT4ge1xuICAgICAgcm9vdC5xdWVyeVNlbGVjdG9yQWxsKCcqJykuZm9yRWFjaCgoZWwpID0+IHtcbiAgICAgICAgaWYgKGVsLnRhZ05hbWUuaW5jbHVkZXMoJy0nKSkge1xuICAgICAgICAgIGVsLnNldEF0dHJpYnV0ZSgnZGF0YS10aGVtZScsIHRoZW1lKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZWwuc2hhZG93Um9vdCkge1xuICAgICAgICAgIHdhbGsoZWwuc2hhZG93Um9vdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG4gICAgLy8gV2FsayBsaWdodCBET00gY2hpbGRyZW4gKHNsb3R0ZWQgcGFnZSBjb21wb25lbnRzIGxpa2UgZG9jcy1ob21lLCB1aS1zaG93Y2FzZSlcbiAgICB3YWxrKHRoaXMpO1xuICAgIC8vIFdhbGsgc2hhZG93IERPTSBjb250ZW50IChpbnRlcm5hbCBsYXlvdXQgZWxlbWVudHMpXG4gICAgaWYgKHRoaXMuc2hhZG93Um9vdCkge1xuICAgICAgd2Fsayh0aGlzLnNoYWRvd1Jvb3QpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWN1cnNpdmVseSBzZWFyY2ggZm9yIG9wZW4tbGF5b3V0IGluIHBhcnNlZCBET00sIGluY2x1ZGluZ1xuICAgKiBpbnNpZGUgPHRlbXBsYXRlIHNoYWRvd3Jvb3Rtb2RlPVwib3BlblwiPiAoRFNEIGNvbnRlbnQpLlxuICAgKlxuICAgKiBxdWVyeVNlbGVjdG9yIGRvZXMgbm90IHRyYXZlcnNlIHRlbXBsYXRlIGNvbnRlbnQsIGJ1dCBTU0cgcGFnZXNcbiAgICogd3JhcCBwYWdlIG91dHB1dCBpbiBhIHBhZ2UgY29tcG9uZW50IHdob3NlIHNoYWRvdyByb290IGNvbnRhaW5zXG4gICAqIHRoZSA8b3Blbi1sYXlvdXQ+LlxuICAgKi9cbiAgcHJpdmF0ZSBfZmluZE9wZW5MYXlvdXQocm9vdDogRWxlbWVudCB8IERvY3VtZW50RnJhZ21lbnQpOiBIVE1MRWxlbWVudCB8IG51bGwge1xuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgQXJyYXkuZnJvbShyb290LmNoaWxkcmVuKSkge1xuICAgICAgaWYgKGNoaWxkLnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ29wZW4tbGF5b3V0JykgcmV0dXJuIGNoaWxkIGFzIEhUTUxFbGVtZW50O1xuICAgICAgaWYgKGNoaWxkLnRhZ05hbWUgPT09ICdURU1QTEFURScpIHtcbiAgICAgICAgY29uc3QgZm91bmQgPSB0aGlzLl9maW5kT3BlbkxheW91dCgoY2hpbGQgYXMgSFRNTFRlbXBsYXRlRWxlbWVudCkuY29udGVudCk7XG4gICAgICAgIGlmIChmb3VuZCkgcmV0dXJuIGZvdW5kO1xuICAgICAgfVxuICAgICAgY29uc3QgZm91bmQgPSB0aGlzLl9maW5kT3BlbkxheW91dChjaGlsZCk7XG4gICAgICBpZiAoZm91bmQpIHJldHVybiBmb3VuZDtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBwcml2YXRlIF9hY3RpdmF0ZURlY2xhcmF0aXZlU2hhZG93Um9vdHMocm9vdDogRWxlbWVudCB8IFNoYWRvd1Jvb3QgfCBEb2N1bWVudEZyYWdtZW50KTogdm9pZCB7XG4gICAgY29uc3QgdGVtcGxhdGVzID0gQXJyYXkuZnJvbShcbiAgICAgIHJvb3QucXVlcnlTZWxlY3RvckFsbDxIVE1MVGVtcGxhdGVFbGVtZW50PigndGVtcGxhdGVbc2hhZG93cm9vdG1vZGVdJyksXG4gICAgKTtcblxuICAgIGlmIChcbiAgICAgIHJvb3QgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCAmJlxuICAgICAgcm9vdC5maXJzdEVsZW1lbnRDaGlsZCBpbnN0YW5jZW9mIEhUTUxUZW1wbGF0ZUVsZW1lbnQgJiZcbiAgICAgIHJvb3QuZmlyc3RFbGVtZW50Q2hpbGQuaGFzQXR0cmlidXRlKCdzaGFkb3dyb290bW9kZScpXG4gICAgKSB7XG4gICAgICB0ZW1wbGF0ZXMudW5zaGlmdChyb290LmZpcnN0RWxlbWVudENoaWxkKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHRlbXBsYXRlIG9mIHRlbXBsYXRlcykge1xuICAgICAgY29uc3QgaG9zdCA9IHRlbXBsYXRlLnBhcmVudEVsZW1lbnQ7XG4gICAgICBpZiAoIWhvc3QgfHwgaG9zdC5zaGFkb3dSb290KSB7XG4gICAgICAgIHRlbXBsYXRlLnJlbW92ZSgpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbW9kZSA9IHRlbXBsYXRlLmdldEF0dHJpYnV0ZSgnc2hhZG93cm9vdG1vZGUnKSA9PT0gJ2Nsb3NlZCcgPyAnY2xvc2VkJyA6ICdvcGVuJztcbiAgICAgIGNvbnN0IHNoYWRvdyA9IGhvc3QuYXR0YWNoU2hhZG93KHsgbW9kZSB9KTtcbiAgICAgIHNoYWRvdy5hcHBlbmRDaGlsZCh0ZW1wbGF0ZS5jb250ZW50KTtcbiAgICAgIHRlbXBsYXRlLnJlbW92ZSgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2lzU2hhZG93VGVtcGxhdGUoZWw6IEVsZW1lbnQpOiBlbCBpcyBIVE1MVGVtcGxhdGVFbGVtZW50IHtcbiAgICByZXR1cm4gZWwgaW5zdGFuY2VvZiBIVE1MVGVtcGxhdGVFbGVtZW50ICYmIGVsLmhhc0F0dHJpYnV0ZSgnc2hhZG93cm9vdG1vZGUnKTtcbiAgfVxuXG4gIHByaXZhdGUgX3N5bmNMYXlvdXRBdHRyaWJ1dGVzKG5ld0xheW91dDogSFRNTEVsZW1lbnQsIGxvY2FsZTogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgaW5jb21pbmcgPSBuZXcgU2V0KFxuICAgICAgQXJyYXkuZnJvbShuZXdMYXlvdXQuYXR0cmlidXRlcykubWFwKChhdHRyKSA9PiBhdHRyLm5hbWUpLFxuICAgICk7XG4gICAgY29uc3QgcHJlc2VydmUgPSBuZXcgU2V0KFsnZGF0YS10aGVtZScsICd0aGVtZSddKTtcblxuICAgIGZvciAoY29uc3QgYXR0ciBvZiBBcnJheS5mcm9tKHRoaXMuYXR0cmlidXRlcykpIHtcbiAgICAgIGlmICghaW5jb21pbmcuaGFzKGF0dHIubmFtZSkgJiYgIXByZXNlcnZlLmhhcyhhdHRyLm5hbWUpKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlKGF0dHIubmFtZSk7XG4gICAgICB9XG4gICAgfVxuICAgIGZvciAoY29uc3QgYXR0ciBvZiBBcnJheS5mcm9tKG5ld0xheW91dC5hdHRyaWJ1dGVzKSkge1xuICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUoYXR0ci5uYW1lLCBhdHRyLnZhbHVlKTtcbiAgICB9XG4gICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ2xvY2FsZScsIGxvY2FsZSk7XG4gICAgdGhpcy5zZXRBdHRyaWJ1dGUoXG4gICAgICAnY3VycmVudC1wYXRoJyxcbiAgICAgIG5ld0xheW91dC5nZXRBdHRyaWJ1dGUoJ2N1cnJlbnQtcGF0aCcpIHx8IHRoaXMuX2N1cnJlbnRQYXRoV2l0aG91dExvY2FsZSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVwbGFjZVNoYWRvd1Jvb3RGcm9tTGF5b3V0KG5ld0xheW91dDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcbiAgICBjb25zdCBzaGFkb3dUZW1wbGF0ZSA9IEFycmF5LmZyb20obmV3TGF5b3V0LmNoaWxkcmVuKS5maW5kKChjaGlsZCkgPT5cbiAgICAgIHRoaXMuX2lzU2hhZG93VGVtcGxhdGUoY2hpbGQpXG4gICAgKTtcbiAgICBpZiAoIXNoYWRvd1RlbXBsYXRlIHx8ICF0aGlzLnNoYWRvd1Jvb3QpIHJldHVybjtcblxuICAgIHdoaWxlICh0aGlzLnNoYWRvd1Jvb3QuZmlyc3RDaGlsZCkge1xuICAgICAgdGhpcy5zaGFkb3dSb290LnJlbW92ZUNoaWxkKHRoaXMuc2hhZG93Um9vdC5maXJzdENoaWxkKTtcbiAgICB9XG4gICAgdGhpcy5zaGFkb3dSb290LmFwcGVuZENoaWxkKGRvY3VtZW50LmFkb3B0Tm9kZShzaGFkb3dUZW1wbGF0ZS5jb250ZW50KSk7XG4gICAgdGhpcy5fYWN0aXZhdGVEZWNsYXJhdGl2ZVNoYWRvd1Jvb3RzKHRoaXMuc2hhZG93Um9vdCk7XG4gICAgdGhpcy5fc2V0dXBEZXRhaWxzVG9nZ2xlKCk7XG4gICAgdGhpcy5fdXBkYXRlU3dpdGNoKHRoaXMuc2hhZG93Um9vdCk7XG4gIH1cblxuICAvKiAtLS0gU1BBIG5hdmlnYXRpb24gKGlubGluZWQgZnJvbSBAb3BlbmVsZW1lbnQvcm91dGVyKSAtLS0gKi9cblxuICBwcml2YXRlIF9zZXR1cFNwYU5hdmlnYXRpb24ob3B0czoge1xuICAgIGNvbnRlbnRMb2FkZXI6IChwYXRoOiBzdHJpbmcsIGxvY2FsZTogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+O1xuICAgIG9uQWZ0ZXJTd2FwPzogKHBhdGg6IHN0cmluZywgbG9jYWxlOiBzdHJpbmcpID0+IHZvaWQ7XG4gIH0pOiB2b2lkIHtcbiAgICB0aGlzLl9uYXZPcHRpb25zID0gb3B0cztcblxuICAgIGlmICh0aGlzLnNoYWRvd1Jvb3QpIHtcbiAgICAgIHRoaXMuX3NldHVwQ2xpY2tEZWxlZ2F0aW9uKHRoaXMuc2hhZG93Um9vdCk7XG4gICAgfVxuICAgIHRoaXMuX3NldHVwTmF2aWdhdGlvbkFwaSgpO1xuICAgIHRoaXMuX3NldHVwUG9wU3RhdGUoKTtcbiAgfVxuXG4gIHByaXZhdGUgX3RlYXJkb3duU3BhTmF2aWdhdGlvbigpOiB2b2lkIHtcbiAgICB0aGlzLl9jbGVhbnVwTmF2Py4oKTtcbiAgICB0aGlzLl9jbGVhbnVwTmF2ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX25hdk9wdGlvbnMgPSB1bmRlZmluZWQ7XG4gIH1cblxuICBwcml2YXRlIF9zZXR1cENsaWNrRGVsZWdhdGlvbihyb290OiBTaGFkb3dSb290KTogdm9pZCB7XG4gICAgY29uc3QgaGFuZGxlciA9IChlOiBFdmVudCkgPT4ge1xuICAgICAgY29uc3QgbGluayA9IChlLnRhcmdldCBhcyBIVE1MRWxlbWVudCkuY2xvc2VzdDxIVE1MQW5jaG9yRWxlbWVudD4oJ2EnKTtcbiAgICAgIGlmICghbGluaykgcmV0dXJuO1xuICAgICAgY29uc3QgaHJlZiA9IGxpbmsuZ2V0QXR0cmlidXRlKCdocmVmJyk7XG4gICAgICBpZiAoIWhyZWYpIHJldHVybjtcblxuICAgICAgaWYgKCFpc1NhZmVMYXlvdXRVcmwoaHJlZikgfHwgL15odHRwcz86L2kudGVzdChocmVmKSB8fCBocmVmLnN0YXJ0c1dpdGgoJyMnKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG5cbiAgICAgIGNvbnN0IGlzTGFuZ1N3aXRjaCA9IGxpbmsuY2xhc3NMaXN0LmNvbnRhaW5zKCdsYW5nLXN3aXRjaCcpO1xuICAgICAgaWYgKGlzTGFuZ1N3aXRjaCkge1xuICAgICAgICB0aGlzLl9yZXBsYWNlVG8oaHJlZik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9uYXZpZ2F0ZVRvKGhyZWYpO1xuICAgICAgfVxuICAgIH07XG4gICAgcm9vdC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGhhbmRsZXIpO1xuICAgIGNvbnN0IHByZXYgPSB0aGlzLl9jbGVhbnVwTmF2O1xuICAgIHRoaXMuX2NsZWFudXBOYXYgPSAoKSA9PiB7XG4gICAgICByb290LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgaGFuZGxlcik7XG4gICAgICBwcmV2Py4oKTtcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBfc2V0dXBOYXZpZ2F0aW9uQXBpKCk6IHZvaWQge1xuICAgIGNvbnN0IG5hdiA9IChnbG9iYWxUaGlzIGFzIHR5cGVvZiBnbG9iYWxUaGlzICYgeyBuYXZpZ2F0aW9uPzogTmF2aWdhdGlvbkxpa2UgfSkubmF2aWdhdGlvbjtcbiAgICBpZiAoIW5hdikgcmV0dXJuO1xuXG4gICAgY29uc3Qgb25OYXY6IEV2ZW50TGlzdGVuZXIgPSAoZXZlbnQpID0+IHtcbiAgICAgIGNvbnN0IGUgPSBldmVudCBhcyBOYXZpZ2F0aW9uTmF2aWdhdGVFdmVudDtcbiAgICAgIGlmICghZS5jYW5JbnRlcmNlcHQgfHwgZS5oYXNoQ2hhbmdlIHx8IGUuZG93bmxvYWRSZXF1ZXN0KSByZXR1cm47XG5cbiAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwoZS5kZXN0aW5hdGlvbi51cmwpO1xuICAgICAgaWYgKHVybC5vcmlnaW4gIT09IGxvY2F0aW9uLm9yaWdpbikgcmV0dXJuO1xuXG4gICAgICBlLmludGVyY2VwdCh7XG4gICAgICAgIGhhbmRsZXI6ICgpID0+IHRoaXMuX25hdmlnYXRlTm93KHVybC5wYXRobmFtZSksXG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdHJ5IHtcbiAgICAgIG5hdi5hZGRFdmVudExpc3RlbmVyKCduYXZpZ2F0ZScsIG9uTmF2KTtcbiAgICAgIGNvbnN0IHByZXYgPSB0aGlzLl9jbGVhbnVwTmF2O1xuICAgICAgdGhpcy5fY2xlYW51cE5hdiA9ICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBuYXYucmVtb3ZlRXZlbnRMaXN0ZW5lcignbmF2aWdhdGUnLCBvbk5hdik7XG4gICAgICAgIH0gY2F0Y2ggeyAvKiAqLyB9XG4gICAgICAgIHByZXY/LigpO1xuICAgICAgfTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIE5hdmlnYXRpb24gQVBJIGludGVyY2VwdGlvbiBpcyBvcHRpb25hbDsgZmFsbCBiYWNrIHRvIHBvcHN0YXRlIHJvdXRpbmcuXG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfc2V0dXBQb3BTdGF0ZSgpOiB2b2lkIHtcbiAgICBjb25zdCBoYW5kbGVyID0gKCkgPT4ge1xuICAgICAgdGhpcy5fbmF2aWdhdGVOb3cobG9jYXRpb24ucGF0aG5hbWUpO1xuICAgIH07XG4gICAgZ2xvYmFsVGhpcy5hZGRFdmVudExpc3RlbmVyKCdwb3BzdGF0ZScsIGhhbmRsZXIpO1xuICAgIGNvbnN0IHByZXYgPSB0aGlzLl9jbGVhbnVwTmF2O1xuICAgIHRoaXMuX2NsZWFudXBOYXYgPSAoKSA9PiB7XG4gICAgICBnbG9iYWxUaGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3BvcHN0YXRlJywgaGFuZGxlcik7XG4gICAgICBwcmV2Py4oKTtcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBfbmF2aWdhdGVUbyhocmVmOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCB1cmwgPSBuZXcgVVJMKGhyZWYsIGxvY2F0aW9uLm9yaWdpbik7XG4gICAgaWYgKHVybC5vcmlnaW4gIT09IGxvY2F0aW9uLm9yaWdpbikge1xuICAgICAgbG9jYXRpb24uaHJlZiA9IGhyZWY7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaGlzdG9yeS5wdXNoU3RhdGUobnVsbCwgJycsIHVybC5wYXRobmFtZSArIHVybC5zZWFyY2ggKyB1cmwuaGFzaCk7XG4gICAgdGhpcy5fbmF2aWdhdGVOb3codXJsLnBhdGhuYW1lKTtcbiAgfVxuXG4gIHByaXZhdGUgX3JlcGxhY2VUbyhocmVmOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCB1cmwgPSBuZXcgVVJMKGhyZWYsIGxvY2F0aW9uLm9yaWdpbik7XG4gICAgaWYgKHVybC5vcmlnaW4gIT09IGxvY2F0aW9uLm9yaWdpbikgcmV0dXJuO1xuXG4gICAgaGlzdG9yeS5yZXBsYWNlU3RhdGUobnVsbCwgJycsIHVybC5wYXRobmFtZSArIHVybC5zZWFyY2ggKyB1cmwuaGFzaCk7XG4gICAgdGhpcy5fbmF2aWdhdGVOb3codXJsLnBhdGhuYW1lKTtcbiAgfVxuXG4gIHByaXZhdGUgX25hdmlnYXRlTm93KHBhdGhuYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBsb2NhbGUgPSBkZXRlY3RMb2NhbGUocGF0aG5hbWUsIHRoaXMuX2xvY2FsZXMsIHRoaXMuX2RlZmF1bHRMb2NhbGUpO1xuICAgIHRoaXMuc2V0QXR0cmlidXRlKCdjdXJyZW50LXBhdGgnLCBwYXRobmFtZSk7XG4gICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ2xvY2FsZScsIGxvY2FsZSk7XG5cbiAgICBjb25zdCBvcHRzID0gdGhpcy5fbmF2T3B0aW9ucztcbiAgICBpZiAoIW9wdHMpIHJldHVybjtcblxuICAgIC8vIFVwZGF0ZSBsYW5nLXN3aXRjaCBpbW1lZGlhdGVseSAoYmVmb3JlIGFzeW5jIGZldGNoKVxuICAgIGlmICh0aGlzLnNoYWRvd1Jvb3QpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZVN3aXRjaCh0aGlzLnNoYWRvd1Jvb3QpO1xuICAgIH1cblxuICAgIG9wdHMuY29udGVudExvYWRlcihwYXRobmFtZSwgbG9jYWxlKS50aGVuKCgpID0+IHtcbiAgICAgIGlmICh0aGlzLnNoYWRvd1Jvb3QpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlU3dpdGNoKHRoaXMuc2hhZG93Um9vdCk7XG4gICAgICB9XG4gICAgICBvcHRzLm9uQWZ0ZXJTd2FwPy4ocGF0aG5hbWUsIGxvY2FsZSk7XG4gICAgfSkuY2F0Y2goKGVycikgPT4ge1xuICAgICAgbG9nLndhcm4oJ2NvbnRlbnQgbG9hZCBmYWlsZWQ6JywgZXJyKTtcbiAgICAgIGxvY2F0aW9uLnJlbG9hZCgpO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfdXBkYXRlU3dpdGNoKHNoYWRvd1Jvb3Q6IFNoYWRvd1Jvb3QpOiB2b2lkIHtcbiAgICBjb25zdCBsaW5rID0gc2hhZG93Um9vdC5xdWVyeVNlbGVjdG9yKCcubGFuZy1zd2l0Y2gnKSBhcyBIVE1MQW5jaG9yRWxlbWVudCB8IG51bGw7XG4gICAgaWYgKCFsaW5rKSByZXR1cm47XG4gICAgY29uc3QgcGF0aFdpdGhvdXRMb2NhbGUgPSB0aGlzLl9jdXJyZW50UGF0aFdpdGhvdXRMb2NhbGU7XG4gICAgY29uc3QgY3VycmVudExvY2FsZSA9IHRoaXMuX2N1cnJlbnRMb2NhbGU7XG4gICAgbGluay50ZXh0Q29udGVudCA9IHN3aXRjaExhYmVsKGN1cnJlbnRMb2NhbGUpO1xuICAgIGxpbmsuc2V0QXR0cmlidXRlKCdocmVmJywgc3dpdGNoUGF0aChwYXRoV2l0aG91dExvY2FsZSwgY3VycmVudExvY2FsZSwgdGhpcy5fbG9jYWxlcykpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBfbG9hZENvbnRlbnQocGF0aDogc3RyaW5nLCBsb2NhbGU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgZmV0Y2gocGF0aCk7XG4gICAgICBpZiAoIXJlc3Aub2spIHRocm93IG5ldyBFcnJvcihgSFRUUCAke3Jlc3Auc3RhdHVzfWApO1xuICAgICAgY29uc3QgaHRtbCA9IGF3YWl0IHJlc3AudGV4dCgpO1xuICAgICAgY29uc3QgcGFyc2VkID0gbmV3IERPTVBhcnNlcigpLnBhcnNlRnJvbVN0cmluZyhodG1sLCAndGV4dC9odG1sJyk7XG4gICAgICBjb25zdCB0bXAgPSBwYXJzZWQuYm9keTtcbiAgICAgIGNvbnN0IG5ld0xheW91dCA9IHRoaXMuX2ZpbmRPcGVuTGF5b3V0KHRtcCk7XG4gICAgICBpZiAoIW5ld0xheW91dCkgdGhyb3cgbmV3IEVycm9yKCdObyBvcGVuLWxheW91dCBmb3VuZCcpO1xuXG4gICAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQubGFuZyA9IHBhcnNlZC5kb2N1bWVudEVsZW1lbnQubGFuZyB8fCBsb2NhbGU7XG4gICAgICBpZiAocGFyc2VkLnRpdGxlKSBkb2N1bWVudC50aXRsZSA9IHBhcnNlZC50aXRsZTtcbiAgICAgIHRoaXMuX3N5bmNIZWFkRWxlbWVudChwYXJzZWQsICdtZXRhW25hbWU9XCJkZXNjcmlwdGlvblwiXScpO1xuICAgICAgdGhpcy5fc3luY0hlYWRFbGVtZW50KHBhcnNlZCwgJ2xpbmtbcmVsPVwiY2Fub25pY2FsXCJdJyk7XG4gICAgICB0aGlzLl9zeW5jSGVhZEVsZW1lbnRzKHBhcnNlZCwgJ2xpbmtbcmVsPVwiYWx0ZXJuYXRlXCJdW2hyZWZsYW5nXScpO1xuXG4gICAgICB0aGlzLl9zeW5jTGF5b3V0QXR0cmlidXRlcyhuZXdMYXlvdXQsIGxvY2FsZSk7XG4gICAgICB0aGlzLl9yZXBsYWNlU2hhZG93Um9vdEZyb21MYXlvdXQobmV3TGF5b3V0KTtcblxuICAgICAgLy8gRE9NUGFyc2VyIG5vZGVzIGJlbG9uZyB0byBhIGRpZmZlcmVudCBkb2N1bWVudC4gYWRvcHROb2RlKClcbiAgICAgIC8vIHRyYW5zZmVycyBvd25lcnNoaXAgc28gYXBwZW5kQ2hpbGQgd29ya3Mgd2l0aG91dCBlcnJvcnMuXG4gICAgICB3aGlsZSAodGhpcy5maXJzdENoaWxkKSB0aGlzLnJlbW92ZUNoaWxkKHRoaXMuZmlyc3RDaGlsZCk7XG4gICAgICBjb25zdCBjaGlsZHJlbiA9IEFycmF5LmZyb20obmV3TGF5b3V0LmNoaWxkcmVuKS5maWx0ZXIoKGNoaWxkKSA9PlxuICAgICAgICAhdGhpcy5faXNTaGFkb3dUZW1wbGF0ZShjaGlsZClcbiAgICAgICk7XG4gICAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIGNoaWxkcmVuKSB7XG4gICAgICAgIGNvbnN0IGFkb3B0ZWQgPSBkb2N1bWVudC5hZG9wdE5vZGUoY2hpbGQpO1xuICAgICAgICBpZiAoYWRvcHRlZCBpbnN0YW5jZW9mIEVsZW1lbnQpIHtcbiAgICAgICAgICB0aGlzLl9hY3RpdmF0ZURlY2xhcmF0aXZlU2hhZG93Um9vdHMoYWRvcHRlZCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hcHBlbmRDaGlsZChhZG9wdGVkKTtcbiAgICAgIH1cblxuICAgICAgLy8gUHJvcGFnYXRlIHRoZW1lIHRvIG5ld2x5IGluc2VydGVkIGNvbXBvbmVudHMuXG4gICAgICBjb25zdCBjdXJyZW50VGhlbWUgPSB0aGlzLmdldEF0dHJpYnV0ZSgnZGF0YS10aGVtZScpIHx8XG4gICAgICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudD8uZGF0YXNldD8udGhlbWU7XG4gICAgICBpZiAoY3VycmVudFRoZW1lKSB7XG4gICAgICAgIHRoaXMuX3Byb3BhZ2F0ZVRoZW1lKGN1cnJlbnRUaGVtZSk7XG4gICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB0aGlzLl9wcm9wYWdhdGVUaGVtZShjdXJyZW50VGhlbWUpKTtcbiAgICAgIH1cblxuICAgICAgZ2xvYmFsVGhpcy5zY3JvbGxUbyh7IHRvcDogMCwgYmVoYXZpb3I6ICdzbW9vdGgnIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxvZy53YXJuKCdTUEEgbmF2aWdhdGlvbiBmYWlsZWQsIHJlbG9hZGluZzonLCBlKTtcbiAgICAgIGdsb2JhbFRoaXMubG9jYXRpb24ucmVsb2FkKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfc3luY0hlYWRFbGVtZW50KHBhcnNlZDogRG9jdW1lbnQsIHNlbGVjdG9yOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBpbmNvbWluZyA9IHBhcnNlZC5oZWFkLnF1ZXJ5U2VsZWN0b3Ioc2VsZWN0b3IpO1xuICAgIGNvbnN0IGN1cnJlbnQgPSBkb2N1bWVudC5oZWFkLnF1ZXJ5U2VsZWN0b3Ioc2VsZWN0b3IpO1xuICAgIGlmICghaW5jb21pbmcpIHtcbiAgICAgIGN1cnJlbnQ/LnJlbW92ZSgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBjbG9uZWQgPSBkb2N1bWVudC5hZG9wdE5vZGUoaW5jb21pbmcuY2xvbmVOb2RlKHRydWUpKTtcbiAgICBpZiAoY3VycmVudCkgY3VycmVudC5yZXBsYWNlV2l0aChjbG9uZWQpO1xuICAgIGVsc2UgZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChjbG9uZWQpO1xuICB9XG5cbiAgcHJpdmF0ZSBfc3luY0hlYWRFbGVtZW50cyhwYXJzZWQ6IERvY3VtZW50LCBzZWxlY3Rvcjogc3RyaW5nKTogdm9pZCB7XG4gICAgZG9jdW1lbnQuaGVhZC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKS5mb3JFYWNoKChlbCkgPT4gZWwucmVtb3ZlKCkpO1xuICAgIHBhcnNlZC5oZWFkLnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpLmZvckVhY2goKGVsKSA9PiB7XG4gICAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKGRvY3VtZW50LmFkb3B0Tm9kZShlbC5jbG9uZU5vZGUodHJ1ZSkpKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX3VwZGF0ZUFjdGl2ZU5hdigpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc2hhZG93Um9vdCkgcmV0dXJuO1xuICAgIGNvbnN0IGNwID0gdGhpcy5fY3VycmVudFBhdGgoKTtcbiAgICBjb25zdCBsaW5rcyA9IHRoaXMuc2hhZG93Um9vdC5xdWVyeVNlbGVjdG9yQWxsKFxuICAgICAgJy5kb2NzLXNpZGViYXIgYVtkYXRhLW5hdl0sIC5oZWFkZXItbmF2IGFbZGF0YS1uYXZdJyxcbiAgICApO1xuICAgIGxpbmtzLmZvckVhY2goKGEpID0+IHtcbiAgICAgIGNvbnN0IG5hdiA9IGEuZ2V0QXR0cmlidXRlKCdkYXRhLW5hdicpO1xuICAgICAgY29uc3QgaXNBY3RpdmUgPSBuYXYgPT09IGNwO1xuICAgICAgYS5jbGFzc0xpc3QudG9nZ2xlKCdhY3RpdmUnLCBpc0FjdGl2ZSk7XG4gICAgICBpZiAoaXNBY3RpdmUpIGEuc2V0QXR0cmlidXRlKCdhcmlhLWN1cnJlbnQnLCAncGFnZScpO1xuICAgICAgZWxzZSBhLnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1jdXJyZW50Jyk7XG4gICAgfSk7XG4gIH1cblxuICAvLyAtLS0gVXRpbGl0aWVzIC0tLVxuXG4gIHByaXZhdGUgX2VzYyA9IGVzY2FwZUh0bWw7XG4gIHByaXZhdGUgX2VzY0F0dHIgPSBlc2NhcGVBdHRyO1xufVxuXG5leHBvcnQgZGVmYXVsdCBPcGVuTGF5b3V0O1xuXG4vLyBHdWFyZDogaWRlbXBvdGVudCBhY3Jvc3MgU1NSIHBhdGhzXG5pZiAodHlwZW9mIGN1c3RvbUVsZW1lbnRzICE9PSAndW5kZWZpbmVkJyAmJiAhY3VzdG9tRWxlbWVudHMuZ2V0KHRhZ05hbWUpKSB7XG4gIGN1c3RvbUVsZW1lbnRzLmRlZmluZSh0YWdOYW1lLCBPcGVuTGF5b3V0KTtcbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx1Q0FBdUMsR0FDdkM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Q0E0QkMsR0FFRCxTQUFTLFdBQVcsUUFBUSx1QkFBdUI7QUFDbkQsU0FBUyxVQUFVLFFBQTZCLGdDQUFnQztBQUNoRixTQUF1QixhQUFhLEVBQUUsY0FBYyxRQUFRLG9CQUFvQjtBQUNoRixTQUFTLFVBQVUsRUFBRSxVQUFVLFFBQVEsb0JBQW9CO0FBQzNELFNBQVMsWUFBWSxRQUFRLDJCQUEyQjtBQUN4RCxPQUFPLDBCQUEwQjtBQUNqQyxPQUFPLHVCQUF1QjtBQUU5QixPQUFPLE1BQU0sVUFBVSxjQUFjO0FBQ3JDLE1BQU0sbUJBQW1CLElBQUksSUFBSTtFQUFDO0VBQVM7RUFBVTtFQUFXO0VBQVE7Q0FBTztBQUMvRSxNQUFNLE1BQU0sYUFBYTtBQUV6QixTQUFTLGdCQUFnQixHQUFXO0VBQ2xDLE1BQU0sVUFBVSxJQUFJLElBQUk7RUFDeEIsSUFBSSxDQUFDLFNBQVMsT0FBTztFQUNyQixJQUFJLFFBQVEsVUFBVSxDQUFDLE9BQU8sT0FBTztFQUNyQyxJQUNFLFFBQVEsVUFBVSxDQUFDLFFBQ25CLFFBQVEsVUFBVSxDQUFDLFFBQ25CLFFBQVEsVUFBVSxDQUFDLFNBQ25CLFFBQVEsVUFBVSxDQUFDLFFBQ25CO0lBQ0EsT0FBTztFQUNUO0VBQ0EsSUFBSTtJQUNGLE1BQU0sU0FBUyxJQUFJ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