vite-plugin-opencode-assistant 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js ADDED
@@ -0,0 +1,1549 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview OpenCode 挂件客户端脚本
4
+ * @description 用于在浏览器中显示 OpenCode AI 助手挂件
5
+ */
6
+ (function () {
7
+ 'use strict';
8
+ /** @type {string} 初始化标记 */
9
+ const INIT_MARKER = '__OPENCODE_INITIALIZED__';
10
+ /** @type {string} 选中元素存储键 */
11
+ const SELECTED_ELEMENTS_KEY = '__opencode_selected_elements__';
12
+ /** @type {number} 服务器同步间隔(毫秒) */
13
+ const SERVER_SYNC_INTERVAL = 2000;
14
+ /** @type {number} 检查 Vue Inspector 间隔(毫秒) */
15
+ const INSPECTOR_CHECK_INTERVAL = 500;
16
+ /** @type {number} 自动打开延迟(毫秒) */
17
+ const AUTO_OPEN_DELAY = 1000;
18
+ /** @type {number} 通知显示时间(毫秒) */
19
+ const NOTIFICATION_DURATION = 3000;
20
+ /**
21
+ * @typedef {Object} HotkeyConfig
22
+ * @property {boolean} ctrl - 是否需要 Ctrl/Meta 键
23
+ * @property {boolean} shift - 是否需要 Shift 键
24
+ * @property {boolean} alt - 是否需要 Alt 键
25
+ * @property {string} key - 主键
26
+ */
27
+ /**
28
+ * @typedef {Object} SelectedElement
29
+ * @property {string|null} filePath - 文件路径
30
+ * @property {number|null} line - 行号
31
+ * @property {number|null} column - 列号
32
+ * @property {string} innerText - 元素内部文本
33
+ * @property {string} description - 元素描述(标签名+选择器)
34
+ */
35
+ /**
36
+ * @typedef {Object} WidgetConfig
37
+ * @property {string} webUrl - Web 服务 URL
38
+ * @property {string} position - 挂件位置
39
+ * @property {string} theme - 主题模式
40
+ * @property {boolean} open - 是否自动打开
41
+ * @property {string} sessionUrl - 会话 URL
42
+ * @property {boolean} lazy - 是否懒加载
43
+ * @property {string} hotkey - 快捷键配置
44
+ */
45
+ /**
46
+ * 初始化 OpenCode 挂件
47
+ * @param {WidgetConfig} config - 挂件配置
48
+ */
49
+ function initOpenCodeWidget(config) {
50
+ if (window[INIT_MARKER])
51
+ return;
52
+ window[INIT_MARKER] = true;
53
+ const { webUrl, position, theme, open, sessionUrl, lazy, hotkey, cwd } = config;
54
+ /** @type {string} 当前页面 URL */
55
+ let currentPageUrl = '';
56
+ /** @type {string} 当前页面标题 */
57
+ let currentPageTitle = '';
58
+ /** @type {boolean} 服务是否已启动 */
59
+ let servicesStarted = !lazy;
60
+ /** @type {boolean} 挂件是否打开 */
61
+ let isOpen = false;
62
+ /**
63
+ * 解析快捷键字符串
64
+ * @param {string} hotkeyStr - 快捷键字符串,如 'ctrl+k'
65
+ * @returns {HotkeyConfig} 快捷键配置
66
+ */
67
+ function parseHotkey(hotkeyStr) {
68
+ if (!hotkeyStr)
69
+ return { ctrl: true, shift: false, alt: false, key: 'k' };
70
+ const parts = hotkeyStr.toLowerCase().split('+');
71
+ const key = parts.pop();
72
+ return {
73
+ ctrl: parts.includes('ctrl') || parts.includes('cmd') || parts.includes('meta'),
74
+ shift: parts.includes('shift'),
75
+ alt: parts.includes('alt'),
76
+ key: key || 'k'
77
+ };
78
+ }
79
+ /** @type {HotkeyConfig} 主快捷键配置 */
80
+ const mainHotkey = parseHotkey(hotkey);
81
+ /**
82
+ * 检查键盘事件是否匹配快捷键
83
+ * @param {KeyboardEvent} e - 键盘事件
84
+ * @param {HotkeyConfig} hotkeyConfig - 快捷键配置
85
+ * @returns {boolean} 是否匹配
86
+ */
87
+ function matchHotkey(e, hotkeyConfig) {
88
+ const ctrlMatch = hotkeyConfig.ctrl ? (e.ctrlKey || e.metaKey) : !(e.ctrlKey || e.metaKey);
89
+ const shiftMatch = hotkeyConfig.shift ? e.shiftKey : !e.shiftKey;
90
+ const altMatch = hotkeyConfig.alt ? e.altKey : !e.altKey;
91
+ const keyMatch = e.key.toLowerCase() === hotkeyConfig.key.toLowerCase();
92
+ return ctrlMatch && shiftMatch && altMatch && keyMatch;
93
+ }
94
+ /**
95
+ * 从 sessionStorage 加载选中的元素
96
+ * @returns {SelectedElement[]} 选中的元素列表
97
+ */
98
+ function loadSelectedElements() {
99
+ try {
100
+ const stored = sessionStorage.getItem(SELECTED_ELEMENTS_KEY);
101
+ if (stored) {
102
+ return JSON.parse(stored);
103
+ }
104
+ }
105
+ catch (e) {
106
+ // 忽略错误
107
+ }
108
+ return [];
109
+ }
110
+ /**
111
+ * 保存选中的元素到 sessionStorage
112
+ * @param {SelectedElement[]} elements - 选中的元素列表
113
+ */
114
+ function saveSelectedElements(elements) {
115
+ try {
116
+ sessionStorage.setItem(SELECTED_ELEMENTS_KEY, JSON.stringify(elements));
117
+ }
118
+ catch (e) {
119
+ // 忽略错误
120
+ }
121
+ }
122
+ /** @type {SelectedElement[]} 选中的元素列表 */
123
+ let selectedElements = loadSelectedElements();
124
+ /**
125
+ * 确保服务已启动
126
+ * @returns {Promise<boolean>} 是否成功启动
127
+ */
128
+ async function ensureServicesStarted() {
129
+ if (servicesStarted)
130
+ return true;
131
+ try {
132
+ const res = await fetch('/__opencode_start__');
133
+ const data = await res.json();
134
+ if (data.success) {
135
+ servicesStarted = true;
136
+ if (data.sessionUrl && iframe) {
137
+ iframe.src = data.sessionUrl;
138
+ }
139
+ return true;
140
+ }
141
+ }
142
+ catch (e) {
143
+ console.error('[OpenCode Widget] Failed to start services:', e);
144
+ }
145
+ return false;
146
+ }
147
+ /**
148
+ * 更新页面上下文
149
+ * @param {boolean} [force=false] - 是否强制更新
150
+ */
151
+ function updateContext(force = false) {
152
+ if (!servicesStarted)
153
+ return;
154
+ const newUrl = window.location.href;
155
+ const newTitle = document.title;
156
+ if (force || newUrl !== currentPageUrl || newTitle !== currentPageTitle) {
157
+ currentPageUrl = newUrl;
158
+ currentPageTitle = newTitle;
159
+ fetch('/__opencode_context__', {
160
+ method: 'POST',
161
+ headers: { 'Content-Type': 'application/json' },
162
+ body: JSON.stringify({ url: newUrl, title: newTitle, selectedElements })
163
+ }).catch(() => { });
164
+ }
165
+ }
166
+ // 监听路由变化
167
+ const originalPushState = history.pushState;
168
+ const originalReplaceState = history.replaceState;
169
+ history.pushState = function (...args) {
170
+ originalPushState.apply(this, args);
171
+ setTimeout(updateContext, 0);
172
+ };
173
+ history.replaceState = function (...args) {
174
+ originalReplaceState.apply(this, args);
175
+ setTimeout(updateContext, 0);
176
+ };
177
+ window.addEventListener('popstate', () => setTimeout(updateContext, 0));
178
+ window.addEventListener('hashchange', () => setTimeout(updateContext, 0));
179
+ // 监听标题变化
180
+ const titleObserver = new MutationObserver(() => {
181
+ if (document.title !== currentPageTitle) {
182
+ updateContext();
183
+ }
184
+ });
185
+ if (document.head) {
186
+ titleObserver.observe(document.head, { childList: true, subtree: true });
187
+ }
188
+ if (servicesStarted) {
189
+ updateContext(true);
190
+ }
191
+ /** @type {string} iframe URL */
192
+ const iframeUrl = sessionUrl || webUrl;
193
+ // 创建样式
194
+ const style = document.createElement('style');
195
+ style.textContent = buildWidgetStyles();
196
+ document.head.appendChild(style);
197
+ // 创建容器
198
+ const container = document.createElement('div');
199
+ container.className = `opencode-widget ${position}`;
200
+ // 创建按钮
201
+ const button = document.createElement('button');
202
+ button.className = 'opencode-button';
203
+ button.innerHTML = `
204
+ <svg t="1775402599580" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns=" http://www.w3.org/2000/svg " p-id="5390" xmlns:xlink=" http://www.w3.org/1999/xlink " width="200" height="200"><path d="M512 981.33H85.34c-15.85 0-30.38-8.77-37.77-22.81a42.624 42.624 0 0 1 2.6-44.02L135 791.08C75.25 710.5 42.67 612.6 42.67 512 42.67 253.21 253.21 42.67 512 42.67S981.34 253.21 981.34 512 770.8 981.33 512 981.33zM166.44 896H512c211.73 0 384-172.27 384-384S723.73 128 512 128 128 300.27 128 512c0 91.29 32.83 179.9 92.46 249.46 12.58 14.69 13.73 36 2.77 51.94L166.44 896z" fill="white" p-id="5391"></path><path d="M384 448m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z" fill="white" p-id="5392"></path><path d="M640 448m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z" fill="white" p-id="5393"></path></svg>
205
+ `;
206
+ button.setAttribute('aria-label', 'Open AI Assistant');
207
+ // 创建聊天面板
208
+ const chat = document.createElement('div');
209
+ chat.className = 'opencode-chat';
210
+ // 创建会话列表
211
+ const sessionList = document.createElement('div');
212
+ sessionList.className = 'opencode-session-list collapsed';
213
+ // 创建折叠按钮
214
+ const toggleBtn = document.createElement('button');
215
+ toggleBtn.className = 'opencode-session-toggle';
216
+ toggleBtn.innerHTML = `
217
+ <svg viewBox="0 0 24 24" width="16" height="16" xmlns="http://www.w3.org/2000/svg">
218
+ <path d="M4 6h16M4 12h16M4 18h16" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
219
+ </svg>
220
+ `;
221
+ toggleBtn.title = '展开会话列表';
222
+ // 创建会话列表头部
223
+ const sessionListHeader = document.createElement('div');
224
+ sessionListHeader.className = 'opencode-session-list-header';
225
+ sessionListHeader.innerHTML = `
226
+ <span>会话列表</span>
227
+ <button class="opencode-new-session-btn" title="新建会话">+</button>
228
+ `;
229
+ // 创建会话列表内容
230
+ const sessionListContent = document.createElement('div');
231
+ sessionListContent.className = 'opencode-session-list-content';
232
+ sessionList.appendChild(toggleBtn);
233
+ sessionList.appendChild(sessionListHeader);
234
+ sessionList.appendChild(sessionListContent);
235
+ // 折叠/展开会话列表
236
+ let isSessionListCollapsed = true;
237
+ function toggleSessionList() {
238
+ isSessionListCollapsed = !isSessionListCollapsed;
239
+ sessionList.classList.toggle('collapsed', isSessionListCollapsed);
240
+ toggleBtn.title = isSessionListCollapsed ? '展开会话列表' : '折叠会话列表';
241
+ }
242
+ toggleBtn.addEventListener('click', toggleSessionList);
243
+ // 创建 iframe 容器
244
+ const iframeContainer = document.createElement('div');
245
+ iframeContainer.className = 'opencode-iframe-container';
246
+ // 创建加载指示器
247
+ const loadingOverlay = document.createElement('div');
248
+ loadingOverlay.className = 'opencode-loading-overlay';
249
+ loadingOverlay.innerHTML = `
250
+ <div class="opencode-loading-spinner"></div>
251
+ <div class="opencode-loading-text">加载中...</div>
252
+ `;
253
+ // 创建 iframe
254
+ const iframe = document.createElement('iframe');
255
+ iframe.className = 'opencode-iframe';
256
+ iframe.src = servicesStarted ? iframeUrl : 'about:blank';
257
+ iframe.allow = 'clipboard-write; clipboard-read';
258
+ iframe.referrerPolicy = 'origin';
259
+ iframe.onload = function () {
260
+ if (servicesStarted) {
261
+ updateContext();
262
+ loadSessions();
263
+ }
264
+ hideLoading();
265
+ };
266
+ iframeContainer.appendChild(loadingOverlay);
267
+ iframeContainer.appendChild(iframe);
268
+ // 创建右侧工具栏
269
+ const rightToolbar = document.createElement('div');
270
+ rightToolbar.className = `opencode-right-toolbar${selectedElements.length === 0 ? ' collapsed' : ''}`;
271
+ // 创建元素选择按钮
272
+ const selectButton = document.createElement('button');
273
+ selectButton.className = 'opencode-select-btn';
274
+ selectButton.innerHTML = `
275
+ <svg viewBox="0 0 1024 1024" width="18" height="18" xmlns="http://www.w3.org/2000/svg">
276
+ <path fill="currentColor" d="M512 896a384 384 0 1 0 0-768 384 384 0 0 0 0 768m0 64a448 448 0 1 1 0-896 448 448 0 0 1 0 896"></path><path fill="currentColor" d="M512 96a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V128a32 32 0 0 1 32-32m0 576a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V704a32 32 0 0 1 32-32M96 512a32 32 0 0 1 32-32h192a32 32 0 0 1 0 64H128a32 32 0 0 1-32-32m576 0a32 32 0 0 1 32-32h192a32 32 0 1 1 0 64H704a32 32 0 0 1-32-32"></path>
277
+ </svg>
278
+ `;
279
+ selectButton.title = '选择页面元素';
280
+ // 创建已选节点容器
281
+ const selectedNodesContainer = document.createElement('div');
282
+ selectedNodesContainer.className = 'opencode-selected-nodes';
283
+ rightToolbar.appendChild(selectButton);
284
+ rightToolbar.appendChild(selectedNodesContainer);
285
+ // 创建选择模式常驻提示(固定到页面顶部)
286
+ const selectModeHint = document.createElement('div');
287
+ selectModeHint.className = 'opencode-select-mode-hint';
288
+ selectModeHint.innerHTML = `
289
+ <span>🎯 选择模式已开启 - 点击元素进行选择</span>
290
+ <span class="opencode-hint-shortcut">按 ESC 退出</span>
291
+ `;
292
+ // 创建已选节点气泡容器(气泡按钮上方)
293
+ const selectedBubbles = document.createElement('div');
294
+ selectedBubbles.className = 'opencode-selected-bubbles';
295
+ chat.appendChild(sessionList);
296
+ chat.appendChild(iframeContainer);
297
+ chat.appendChild(rightToolbar);
298
+ container.appendChild(button);
299
+ container.appendChild(selectedBubbles);
300
+ container.appendChild(chat);
301
+ document.body.appendChild(container);
302
+ document.body.appendChild(selectModeHint);
303
+ if (selectedElements.length > 0) {
304
+ renderSelectedNodes();
305
+ }
306
+ /** @type {Array} 会话列表 */
307
+ let sessions = [];
308
+ /** @type {string|null} 当前会话 ID */
309
+ let currentSessionId = null;
310
+ /**
311
+ * 从 URL 中提取会话 ID
312
+ */
313
+ function extractSessionId(url) {
314
+ if (!url)
315
+ return null;
316
+ const match = url.match(/\/session\/([^/?]+)/);
317
+ return match ? match[1] : null;
318
+ }
319
+ // 从初始 URL 中提取会话 ID
320
+ currentSessionId = extractSessionId(sessionUrl);
321
+ /**
322
+ * 显示加载状态
323
+ */
324
+ function showLoading() {
325
+ loadingOverlay.classList.add('visible');
326
+ }
327
+ /**
328
+ * 隐藏加载状态
329
+ */
330
+ function hideLoading() {
331
+ loadingOverlay.classList.remove('visible');
332
+ }
333
+ /**
334
+ * 加载会话列表
335
+ */
336
+ async function loadSessions() {
337
+ try {
338
+ const response = await fetch('/__opencode_sessions__');
339
+ sessions = await response.json();
340
+ renderSessionList();
341
+ }
342
+ catch (e) {
343
+ console.error('Failed to load sessions:', e);
344
+ }
345
+ }
346
+ /**
347
+ * 渲染会话列表
348
+ */
349
+ function renderSessionList() {
350
+ sessionListContent.innerHTML = '';
351
+ const currentProjectSessions = sessions.filter(session => session.directory === cwd);
352
+ currentProjectSessions.forEach(session => {
353
+ const item = document.createElement('div');
354
+ item.className = 'opencode-session-item';
355
+ if (session.id === currentSessionId) {
356
+ item.classList.add('active');
357
+ }
358
+ const header = document.createElement('div');
359
+ header.className = 'opencode-session-header';
360
+ const title = document.createElement('div');
361
+ title.className = 'opencode-session-title';
362
+ title.textContent = session.title || '新会话';
363
+ const deleteBtn = document.createElement('button');
364
+ deleteBtn.className = 'opencode-session-delete-btn';
365
+ deleteBtn.innerHTML = '×';
366
+ deleteBtn.title = '删除会话';
367
+ deleteBtn.addEventListener('click', (e) => {
368
+ e.stopPropagation();
369
+ confirmDeleteSession(session);
370
+ });
371
+ header.appendChild(title);
372
+ header.appendChild(deleteBtn);
373
+ const meta = document.createElement('div');
374
+ meta.className = 'opencode-session-meta';
375
+ const date = new Date(session.time.updated);
376
+ meta.textContent = date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
377
+ item.appendChild(header);
378
+ item.appendChild(meta);
379
+ item.addEventListener('click', () => {
380
+ switchSession(session);
381
+ });
382
+ sessionListContent.appendChild(item);
383
+ });
384
+ }
385
+ /**
386
+ * 切换会话
387
+ */
388
+ function switchSession(session) {
389
+ if (session.id === currentSessionId) {
390
+ return;
391
+ }
392
+ currentSessionId = session.id;
393
+ const encodedDir = btoa(cwd);
394
+ const baseUrl = iframeUrl.split('/').slice(0, 3).join('/');
395
+ showLoading();
396
+ iframe.src = `${baseUrl}/${encodedDir}/session/${session.id}`;
397
+ renderSessionList();
398
+ }
399
+ /**
400
+ * 创建新会话
401
+ */
402
+ async function createNewSession() {
403
+ try {
404
+ const response = await fetch('/__opencode_sessions__', {
405
+ method: 'POST'
406
+ });
407
+ const newSession = await response.json();
408
+ sessions.unshift(newSession);
409
+ switchSession(newSession);
410
+ }
411
+ catch (e) {
412
+ console.error('Failed to create session:', e);
413
+ showNotification('创建会话失败');
414
+ }
415
+ }
416
+ /**
417
+ * 确认删除会话
418
+ */
419
+ function confirmDeleteSession(session) {
420
+ const confirmed = confirm(`确定要删除会话 "${session.title || '新会话'}" 吗?`);
421
+ if (confirmed) {
422
+ deleteSession(session);
423
+ }
424
+ }
425
+ /**
426
+ * 删除会话
427
+ */
428
+ async function deleteSession(session) {
429
+ try {
430
+ const response = await fetch(`/__opencode_sessions__?id=${session.id}`, {
431
+ method: 'DELETE'
432
+ });
433
+ if (!response.ok) {
434
+ throw new Error('Delete failed');
435
+ }
436
+ sessions = sessions.filter(s => s.id !== session.id);
437
+ if (session.id === currentSessionId) {
438
+ const remainingSessions = sessions.filter(s => s.directory === cwd);
439
+ if (remainingSessions.length > 0) {
440
+ switchSession(remainingSessions[0]);
441
+ }
442
+ else {
443
+ currentSessionId = null;
444
+ iframe.src = 'about:blank';
445
+ }
446
+ }
447
+ renderSessionList();
448
+ showNotification('会话已删除');
449
+ }
450
+ catch (e) {
451
+ console.error('Failed to delete session:', e);
452
+ showNotification('删除会话失败');
453
+ }
454
+ }
455
+ // 绑定新建会话按钮
456
+ sessionListHeader.querySelector('.opencode-new-session-btn').addEventListener('click', createNewSession);
457
+ /**
458
+ * 应用主题
459
+ */
460
+ function applyTheme() {
461
+ if (theme === 'auto') {
462
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
463
+ container.classList.toggle('opencode-dark', prefersDark);
464
+ }
465
+ else {
466
+ container.classList.toggle('opencode-dark', theme === 'dark');
467
+ }
468
+ }
469
+ applyTheme();
470
+ if (theme === 'auto') {
471
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', applyTheme);
472
+ }
473
+ /**
474
+ * 切换挂件显示状态
475
+ */
476
+ async function toggle() {
477
+ if (lazy && !servicesStarted) {
478
+ button.classList.add('loading');
479
+ const started = await ensureServicesStarted();
480
+ button.classList.remove('loading');
481
+ if (!started) {
482
+ showNotification('服务启动失败,请检查控制台');
483
+ return;
484
+ }
485
+ }
486
+ isOpen = !isOpen;
487
+ chat.classList.toggle('open', isOpen);
488
+ button.classList.toggle('active', isOpen);
489
+ if (isOpen) {
490
+ updateContext();
491
+ }
492
+ }
493
+ button.addEventListener('click', toggle);
494
+ document.addEventListener('keydown', (e) => {
495
+ if (matchHotkey(e, mainHotkey)) {
496
+ e.preventDefault();
497
+ toggle();
498
+ }
499
+ });
500
+ if (open && servicesStarted) {
501
+ setTimeout(() => {
502
+ toggle();
503
+ }, AUTO_OPEN_DELAY);
504
+ }
505
+ /**
506
+ * 显示通知
507
+ * @param {string} message - 通知消息
508
+ */
509
+ function showNotification(message) {
510
+ const notification = document.createElement('div');
511
+ notification.className = 'opencode-notification';
512
+ notification.textContent = message;
513
+ chat.appendChild(notification);
514
+ setTimeout(() => {
515
+ notification.remove();
516
+ }, NOTIFICATION_DURATION);
517
+ }
518
+ /**
519
+ * 添加选中元素
520
+ * @param {SelectedElement} elementInfo - 元素信息
521
+ */
522
+ function addElement(elementInfo) {
523
+ const key = elementInfo.filePath && elementInfo.line
524
+ ? `${elementInfo.filePath}:${elementInfo.line}`
525
+ : null;
526
+ const exists = key && selectedElements.some(el => {
527
+ const elKey = el.filePath && el.line ? `${el.filePath}:${el.line}` : null;
528
+ return elKey === key;
529
+ });
530
+ if (!exists) {
531
+ selectedElements.push(elementInfo);
532
+ saveSelectedElements(selectedElements);
533
+ renderSelectedNodes();
534
+ if (isSelectMode) {
535
+ renderSelectedBubbles();
536
+ }
537
+ showNotification(`已选中元素 (${selectedElements.length}个)`);
538
+ }
539
+ else {
540
+ showNotification('该元素已选中');
541
+ }
542
+ }
543
+ /**
544
+ * 移除选中元素
545
+ * @param {number} index - 元素索引
546
+ */
547
+ function removeElement(index) {
548
+ selectedElements.splice(index, 1);
549
+ saveSelectedElements(selectedElements);
550
+ renderSelectedNodes();
551
+ updateToolbarState();
552
+ sendSelectedElements();
553
+ }
554
+ /**
555
+ * 清除所有选中元素
556
+ */
557
+ function clearAllElements() {
558
+ selectedElements = [];
559
+ saveSelectedElements(selectedElements);
560
+ renderSelectedNodes();
561
+ updateToolbarState();
562
+ sendSelectedElements();
563
+ showNotification('已清除所有选中元素');
564
+ }
565
+ /**
566
+ * 更新工具栏状态
567
+ */
568
+ function updateToolbarState() {
569
+ if (selectedElements.length > 0) {
570
+ rightToolbar.classList.remove('collapsed');
571
+ }
572
+ else {
573
+ rightToolbar.classList.add('collapsed');
574
+ }
575
+ }
576
+ /** @type {boolean} 是否处于元素选择模式 */
577
+ let isSelectMode = false;
578
+ /**
579
+ * 切换元素选择模式
580
+ */
581
+ function toggleSelectMode() {
582
+ const inspector = window.__VUE_INSPECTOR__;
583
+ if (!inspector) {
584
+ showNotification('Vue Inspector 未加载,无法使用元素选择功能');
585
+ return;
586
+ }
587
+ isSelectMode = !isSelectMode;
588
+ selectButton.classList.toggle('active', isSelectMode);
589
+ selectModeHint.classList.toggle('visible', isSelectMode);
590
+ selectedBubbles.classList.toggle('visible', isSelectMode);
591
+ if (isSelectMode) {
592
+ chat.style.display = 'none';
593
+ inspector.enable();
594
+ renderSelectedBubbles();
595
+ }
596
+ else {
597
+ chat.style.display = '';
598
+ inspector.disable();
599
+ }
600
+ }
601
+ /**
602
+ * 退出选择模式
603
+ */
604
+ function exitSelectMode() {
605
+ if (!isSelectMode)
606
+ return;
607
+ const inspector = window.__VUE_INSPECTOR__;
608
+ if (inspector) {
609
+ inspector.disable();
610
+ }
611
+ isSelectMode = false;
612
+ selectButton.classList.remove('active');
613
+ selectModeHint.classList.remove('visible');
614
+ selectedBubbles.classList.remove('visible');
615
+ chat.style.display = '';
616
+ }
617
+ // ESC 键退出选择模式
618
+ document.addEventListener('keydown', (e) => {
619
+ if (e.key === 'Escape' && isSelectMode) {
620
+ exitSelectMode();
621
+ }
622
+ });
623
+ /**
624
+ * 渲染已选节点气泡
625
+ */
626
+ function renderSelectedBubbles() {
627
+ selectedBubbles.innerHTML = '';
628
+ if (selectedElements.length === 0) {
629
+ selectedBubbles.innerHTML = '<div class="opencode-bubble-empty">暂无选中元素</div>';
630
+ return;
631
+ }
632
+ selectedElements.forEach((element, index) => {
633
+ const bubble = document.createElement('div');
634
+ bubble.className = 'opencode-selected-bubble';
635
+ const description = element.description || '未知元素';
636
+ const fileName = element.filePath ? element.filePath.split('/').pop() : '';
637
+ const lineInfo = element.line ? `:${element.line}` : '';
638
+ bubble.innerHTML = `
639
+ <span class="opencode-bubble-text">${description}</span>
640
+ ${fileName ? `<span class="opencode-bubble-file">${fileName}${lineInfo}</span>` : ''}
641
+ <button class="opencode-bubble-remove" data-index="${index}">×</button>
642
+ `;
643
+ bubble.querySelector('.opencode-bubble-remove').addEventListener('click', (e) => {
644
+ e.stopPropagation();
645
+ removeElement(index);
646
+ renderSelectedBubbles();
647
+ });
648
+ selectedBubbles.appendChild(bubble);
649
+ });
650
+ }
651
+ function renderSelectedNodes() {
652
+ selectedNodesContainer.innerHTML = '';
653
+ if (selectedElements.length === 0) {
654
+ rightToolbar.classList.add('collapsed');
655
+ }
656
+ else {
657
+ rightToolbar.classList.remove('collapsed');
658
+ }
659
+ selectedElements.forEach((element, index) => {
660
+ const node = document.createElement('div');
661
+ node.className = 'opencode-selected-node';
662
+ const description = element.description || '未知元素';
663
+ const textPreview = element.innerText ? element.innerText.substring(0, 30) : '';
664
+ const fileName = element.filePath ? element.filePath.split('/').pop() : '未知文件';
665
+ const lineInfo = element.line ? `:${element.line}` : '';
666
+ node.innerHTML = `
667
+ <div class="opencode-node-content">
668
+ <span class="opencode-node-text">${description}</span>
669
+ <span class="opencode-node-file">${textPreview ? textPreview + ' · ' : ''}${fileName}${lineInfo}</span>
670
+ </div>
671
+ <button class="opencode-node-remove" data-index="${index}">×</button>
672
+ `;
673
+ node.querySelector('.opencode-node-remove').addEventListener('click', (e) => {
674
+ e.stopPropagation();
675
+ removeElement(index);
676
+ });
677
+ selectedNodesContainer.appendChild(node);
678
+ });
679
+ }
680
+ // 绑定选择按钮点击事件
681
+ selectButton.addEventListener('click', toggleSelectMode);
682
+ /**
683
+ * 发送选中元素到服务器
684
+ */
685
+ function sendSelectedElements() {
686
+ if (!servicesStarted)
687
+ return;
688
+ fetch('/__opencode_context__', {
689
+ method: 'POST',
690
+ headers: { 'Content-Type': 'application/json' },
691
+ body: JSON.stringify({
692
+ url: currentPageUrl,
693
+ title: currentPageTitle,
694
+ selectedElements: selectedElements
695
+ })
696
+ }).catch(() => { });
697
+ }
698
+ /**
699
+ * 与服务器同步选中元素
700
+ */
701
+ function syncWithServer() {
702
+ if (!servicesStarted)
703
+ return;
704
+ fetch('/__opencode_context__')
705
+ .then(res => res.json())
706
+ .then(data => {
707
+ if (data.selectedElements && data.selectedElements.length === 0 && selectedElements.length > 0) {
708
+ selectedElements = [];
709
+ saveSelectedElements(selectedElements);
710
+ renderSelectedNodes();
711
+ }
712
+ })
713
+ .catch(() => { });
714
+ }
715
+ setInterval(syncWithServer, SERVER_SYNC_INTERVAL);
716
+ /**
717
+ * 截断字符串
718
+ * @param {string} str - 原字符串
719
+ * @param {number} maxLength - 最大长度
720
+ * @returns {string} 截断后的字符串
721
+ */
722
+ function truncate(str, maxLength) {
723
+ if (!str)
724
+ return '';
725
+ return str.length > maxLength ? str.substring(0, maxLength) + '...' : str;
726
+ }
727
+ /**
728
+ * 获取元素的直接文本内容
729
+ * @param {Element} element - DOM 元素
730
+ * @returns {string} 直接文本内容
731
+ */
732
+ function getDirectText(element) {
733
+ let text = '';
734
+ for (const child of element.childNodes) {
735
+ if (child.nodeType === Node.TEXT_NODE) {
736
+ text += child.textContent || '';
737
+ }
738
+ }
739
+ return text.trim();
740
+ }
741
+ /**
742
+ * 获取元素描述信息
743
+ * @param {Element} element - DOM 元素
744
+ * @returns {string} 元素描述
745
+ */
746
+ function getElementDescription(element) {
747
+ const tag = element.tagName.toLowerCase();
748
+ const parts = [tag];
749
+ const id = element.id;
750
+ if (id)
751
+ parts.push(`#${id}`);
752
+ const className = element.className && typeof element.className === 'string'
753
+ ? element.className.trim().split(/\s+/).filter(Boolean).slice(0, 2).join('.')
754
+ : '';
755
+ if (className)
756
+ parts.push(`.${className}`);
757
+ const name = element.getAttribute('name');
758
+ if (name)
759
+ parts.push(`[name="${name}"]`);
760
+ const placeholder = element.getAttribute('placeholder');
761
+ if (placeholder)
762
+ parts.push(`[placeholder="${placeholder.substring(0, 20)}"]`);
763
+ const src = element.getAttribute('src');
764
+ if (src)
765
+ parts.push(`[src]`);
766
+ const href = element.getAttribute('href');
767
+ if (href && href !== '#')
768
+ parts.push(`[href]`);
769
+ return parts.join('');
770
+ }
771
+ /**
772
+ * 设置 Vue Inspector 钩子
773
+ */
774
+ function setupInspectorHook() {
775
+ if (window.__VUE_INSPECTOR__) {
776
+ const inspector = window.__VUE_INSPECTOR__;
777
+ const originalHandleClick = inspector.handleClick.bind(inspector);
778
+ inspector.handleClick = function (e) {
779
+ if (isSelectMode) {
780
+ const { targetNode, params } = inspector.getTargetNode(e);
781
+ if (targetNode && params) {
782
+ const innerText = getDirectText(targetNode);
783
+ const description = getElementDescription(targetNode);
784
+ const elementInfo = {
785
+ filePath: params.file,
786
+ line: params.line,
787
+ column: params.column,
788
+ innerText: truncate(innerText, 200),
789
+ description
790
+ };
791
+ addElement(elementInfo);
792
+ sendSelectedElements();
793
+ }
794
+ return;
795
+ }
796
+ return originalHandleClick.call(inspector, e);
797
+ };
798
+ }
799
+ }
800
+ if (window.__VUE_INSPECTOR__) {
801
+ setupInspectorHook();
802
+ }
803
+ else {
804
+ const checkInspector = setInterval(() => {
805
+ if (window.__VUE_INSPECTOR__) {
806
+ setupInspectorHook();
807
+ clearInterval(checkInspector);
808
+ }
809
+ }, INSPECTOR_CHECK_INTERVAL);
810
+ }
811
+ // 导出全局 API
812
+ window.OpenCodeWidget = {
813
+ open: () => { if (!isOpen)
814
+ toggle(); },
815
+ close: () => { if (isOpen)
816
+ toggle(); },
817
+ toggle,
818
+ showNotification,
819
+ updateContext,
820
+ };
821
+ }
822
+ /**
823
+ * 构建挂件样式
824
+ * @returns {string} CSS 样式字符串
825
+ */
826
+ function buildWidgetStyles() {
827
+ return `
828
+ .opencode-widget {
829
+ position: fixed;
830
+ z-index: 999999;
831
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
832
+ }
833
+
834
+ .opencode-widget.bottom-right {
835
+ bottom: 20px;
836
+ right: 20px;
837
+ }
838
+
839
+ .opencode-widget.bottom-left {
840
+ bottom: 20px;
841
+ left: 20px;
842
+ }
843
+
844
+ .opencode-widget.top-right {
845
+ top: 20px;
846
+ right: 20px;
847
+ }
848
+
849
+ .opencode-widget.top-left {
850
+ top: 20px;
851
+ left: 20px;
852
+ }
853
+
854
+ .opencode-button {
855
+ width: 60px;
856
+ height: 60px;
857
+ border-radius: 50%;
858
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
859
+ border: none;
860
+ cursor: pointer;
861
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
862
+ transition: all 0.3s ease;
863
+ display: flex;
864
+ align-items: center;
865
+ justify-content: center;
866
+ color: white;
867
+ padding: 0;
868
+ }
869
+
870
+ .opencode-button:hover {
871
+ transform: scale(1.1);
872
+ box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
873
+ background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
874
+ }
875
+
876
+ .opencode-button.active {
877
+ background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
878
+ box-shadow: 0 6px 20px rgba(240, 147, 251, 0.4);
879
+ transform: rotate(180deg);
880
+ }
881
+
882
+ .opencode-button.loading {
883
+ animation: pulse 1s infinite;
884
+ }
885
+
886
+ @keyframes pulse {
887
+ 0%, 100% { opacity: 1; }
888
+ 50% { opacity: 0.5; }
889
+ }
890
+
891
+ .opencode-chat {
892
+ position: absolute;
893
+ width: 700px;
894
+ height: 80vh;
895
+ background: white;
896
+ border-radius: 16px;
897
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
898
+ overflow: hidden;
899
+ opacity: 0;
900
+ visibility: hidden;
901
+ transform: translateY(20px) scale(0.95);
902
+ transition: all 0.3s ease;
903
+ display: flex;
904
+ }
905
+
906
+ .opencode-widget.bottom-right .opencode-chat {
907
+ bottom: 80px;
908
+ right: 0;
909
+ }
910
+
911
+ .opencode-widget.bottom-left .opencode-chat {
912
+ bottom: 80px;
913
+ left: 0;
914
+ }
915
+
916
+ .opencode-widget.top-right .opencode-chat {
917
+ top: 80px;
918
+ right: 0;
919
+ }
920
+
921
+ .opencode-widget.top-left .opencode-chat {
922
+ top: 80px;
923
+ left: 0;
924
+ }
925
+
926
+ .opencode-chat.open {
927
+ opacity: 1;
928
+ visibility: visible;
929
+ transform: translateY(0) scale(1);
930
+ }
931
+
932
+ .opencode-session-list {
933
+ width: 240px;
934
+ background: #f8f9fa;
935
+ border-right: 1px solid #e5e7eb;
936
+ display: flex;
937
+ flex-direction: column;
938
+ flex-shrink: 0;
939
+ transition: width 0.2s ease;
940
+ }
941
+
942
+ .opencode-session-list.collapsed {
943
+ width: 40px;
944
+ }
945
+
946
+ .opencode-session-toggle {
947
+ width: 100%;
948
+ height: 40px;
949
+ border: none;
950
+ background: transparent;
951
+ color: #6b7280;
952
+ cursor: pointer;
953
+ display: flex;
954
+ align-items: center;
955
+ justify-content: center;
956
+ transition: all 0.2s;
957
+ border-bottom: 1px solid #e5e7eb;
958
+ }
959
+
960
+ .opencode-session-toggle:hover {
961
+ background: #e5e7eb;
962
+ color: #374151;
963
+ }
964
+
965
+ .opencode-session-list.collapsed .opencode-session-list-header,
966
+ .opencode-session-list.collapsed .opencode-session-list-content {
967
+ display: none;
968
+ }
969
+
970
+ .opencode-session-list-header {
971
+ padding: 16px;
972
+ border-bottom: 1px solid #e5e7eb;
973
+ display: flex;
974
+ justify-content: space-between;
975
+ align-items: center;
976
+ font-weight: 600;
977
+ font-size: 14px;
978
+ color: #374151;
979
+ }
980
+
981
+ .opencode-new-session-btn {
982
+ width: 28px;
983
+ height: 28px;
984
+ border-radius: 6px;
985
+ border: none;
986
+ background: #3b82f6;
987
+ color: white;
988
+ font-size: 18px;
989
+ cursor: pointer;
990
+ display: flex;
991
+ align-items: center;
992
+ justify-content: center;
993
+ transition: all 0.2s;
994
+ }
995
+
996
+ .opencode-new-session-btn:hover {
997
+ background: #2563eb;
998
+ transform: scale(1.05);
999
+ }
1000
+
1001
+ .opencode-session-list-content {
1002
+ flex: 1;
1003
+ overflow-y: auto;
1004
+ padding: 8px;
1005
+ }
1006
+
1007
+ .opencode-session-item {
1008
+ padding: 12px;
1009
+ border-radius: 8px;
1010
+ cursor: pointer;
1011
+ transition: all 0.2s;
1012
+ margin-bottom: 4px;
1013
+ }
1014
+
1015
+ .opencode-session-item:hover {
1016
+ background: #e5e7eb;
1017
+ }
1018
+
1019
+ .opencode-session-item.active {
1020
+ background: #3b82f6;
1021
+ color: white;
1022
+ }
1023
+
1024
+ .opencode-session-title {
1025
+ font-size: 14px;
1026
+ font-weight: 500;
1027
+ margin-bottom: 4px;
1028
+ overflow: hidden;
1029
+ text-overflow: ellipsis;
1030
+ white-space: nowrap;
1031
+ }
1032
+
1033
+ .opencode-session-meta {
1034
+ font-size: 12px;
1035
+ opacity: 0.6;
1036
+ }
1037
+
1038
+ .opencode-session-header {
1039
+ display: flex;
1040
+ justify-content: space-between;
1041
+ align-items: center;
1042
+ margin-bottom: 4px;
1043
+ }
1044
+
1045
+ .opencode-session-delete-btn {
1046
+ width: 20px;
1047
+ height: 20px;
1048
+ border-radius: 4px;
1049
+ border: none;
1050
+ background: transparent;
1051
+ color: #6b7280;
1052
+ font-size: 16px;
1053
+ cursor: pointer;
1054
+ display: flex;
1055
+ align-items: center;
1056
+ justify-content: center;
1057
+ transition: all 0.2s;
1058
+ opacity: 0;
1059
+ flex-shrink: 0;
1060
+ }
1061
+
1062
+ .opencode-session-item:hover .opencode-session-delete-btn {
1063
+ opacity: 1;
1064
+ }
1065
+
1066
+ .opencode-session-delete-btn:hover {
1067
+ background: #ef4444;
1068
+ color: white;
1069
+ }
1070
+
1071
+ .opencode-session-item.active .opencode-session-delete-btn {
1072
+ color: rgba(255, 255, 255, 0.7);
1073
+ }
1074
+
1075
+ .opencode-session-item.active .opencode-session-delete-btn:hover {
1076
+ background: rgba(255, 255, 255, 0.2);
1077
+ color: white;
1078
+ }
1079
+
1080
+ .opencode-iframe-container {
1081
+ flex: 1;
1082
+ position: relative;
1083
+ overflow: hidden;
1084
+ display: flex;
1085
+ flex-direction: column;
1086
+ }
1087
+
1088
+ .opencode-loading-overlay {
1089
+ position: absolute;
1090
+ top: 0;
1091
+ left: 0;
1092
+ right: 0;
1093
+ bottom: 0;
1094
+ background: rgba(255, 255, 255, 0.9);
1095
+ display: none;
1096
+ flex-direction: column;
1097
+ align-items: center;
1098
+ justify-content: center;
1099
+ z-index: 10;
1100
+ transition: opacity 0.3s ease;
1101
+ }
1102
+
1103
+ .opencode-loading-overlay.visible {
1104
+ display: flex;
1105
+ }
1106
+
1107
+ .opencode-loading-spinner {
1108
+ width: 40px;
1109
+ height: 40px;
1110
+ border: 3px solid #e5e7eb;
1111
+ border-top-color: #3b82f6;
1112
+ border-radius: 50%;
1113
+ animation: spin 0.8s linear infinite;
1114
+ }
1115
+
1116
+ @keyframes spin {
1117
+ to { transform: rotate(360deg); }
1118
+ }
1119
+
1120
+ .opencode-loading-text {
1121
+ margin-top: 12px;
1122
+ font-size: 14px;
1123
+ color: #6b7280;
1124
+ }
1125
+
1126
+ .opencode-iframe {
1127
+ position: absolute;
1128
+ top: -136px;
1129
+ width: 100%;
1130
+ height: calc(100% + 136px);
1131
+ border: none;
1132
+ transition: opacity 0.3s ease;
1133
+ }
1134
+
1135
+ .opencode-dark .opencode-chat {
1136
+ background: #1a1a1a;
1137
+ }
1138
+
1139
+ .opencode-dark .opencode-session-list {
1140
+ background: #111827;
1141
+ border-right-color: #374151;
1142
+ }
1143
+
1144
+ .opencode-dark .opencode-session-toggle {
1145
+ color: #9ca3af;
1146
+ border-bottom-color: #374151;
1147
+ }
1148
+
1149
+ .opencode-dark .opencode-session-toggle:hover {
1150
+ background: #374151;
1151
+ color: #f3f4f6;
1152
+ }
1153
+
1154
+ .opencode-dark .opencode-session-list-header {
1155
+ border-bottom-color: #374151;
1156
+ color: #f3f4f6;
1157
+ }
1158
+
1159
+ .opencode-dark .opencode-session-item:hover {
1160
+ background: #374151;
1161
+ }
1162
+
1163
+ .opencode-dark .opencode-session-item.active {
1164
+ background: #3b82f6;
1165
+ }
1166
+
1167
+ .opencode-dark .opencode-loading-overlay {
1168
+ background: rgba(26, 26, 26, 0.9);
1169
+ }
1170
+
1171
+ .opencode-dark .opencode-loading-spinner {
1172
+ border-color: #374151;
1173
+ border-top-color: #3b82f6;
1174
+ }
1175
+
1176
+ .opencode-dark .opencode-loading-text {
1177
+ color: #9ca3af;
1178
+ }
1179
+
1180
+ .opencode-right-toolbar {
1181
+ width: 140px;
1182
+ background: #f8f9fa;
1183
+ border-left: 1px solid #e5e7eb;
1184
+ display: flex;
1185
+ flex-direction: column;
1186
+ flex-shrink: 0;
1187
+ transition: width 0.2s ease;
1188
+ }
1189
+
1190
+ .opencode-right-toolbar.collapsed {
1191
+ width: 40px;
1192
+ }
1193
+
1194
+ .opencode-right-toolbar.collapsed .opencode-selected-nodes {
1195
+ display: none;
1196
+ }
1197
+
1198
+ .opencode-select-btn {
1199
+ width: 100%;
1200
+ height: 44px;
1201
+ border: none;
1202
+ background: transparent;
1203
+ color: #6b7280;
1204
+ cursor: pointer;
1205
+ display: flex;
1206
+ align-items: center;
1207
+ justify-content: center;
1208
+ gap: 8px;
1209
+ transition: all 0.2s;
1210
+ border-bottom: 1px solid #e5e7eb;
1211
+ font-size: 13px;
1212
+ font-weight: 500;
1213
+ }
1214
+
1215
+ .opencode-select-btn:hover {
1216
+ background: #e5e7eb;
1217
+ color: #374151;
1218
+ }
1219
+
1220
+ .opencode-select-btn.active {
1221
+ background: #3b82f6;
1222
+ color: white;
1223
+ }
1224
+
1225
+ .opencode-selected-nodes {
1226
+ flex: 1;
1227
+ display: flex;
1228
+ flex-direction: column;
1229
+ padding: 8px;
1230
+ gap: 6px;
1231
+ overflow-y: auto;
1232
+ overflow-x: hidden;
1233
+ }
1234
+
1235
+ .opencode-selected-nodes:empty::before {
1236
+ content: '暂无选中元素';
1237
+ color: #9ca3af;
1238
+ font-size: 12px;
1239
+ text-align: center;
1240
+ padding: 20px 10px;
1241
+ }
1242
+
1243
+ .opencode-selected-node {
1244
+ display: flex;
1245
+ align-items: center;
1246
+ gap: 8px;
1247
+ padding: 8px 10px;
1248
+ background: white;
1249
+ border: 1px solid #e5e7eb;
1250
+ border-radius: 6px;
1251
+ font-size: 12px;
1252
+ transition: all 0.2s;
1253
+ }
1254
+
1255
+ .opencode-selected-node:hover {
1256
+ border-color: #3b82f6;
1257
+ box-shadow: 0 2px 4px rgba(59, 130, 246, 0.1);
1258
+ }
1259
+
1260
+ .opencode-node-content {
1261
+ flex: 1;
1262
+ min-width: 0;
1263
+ display: flex;
1264
+ flex-direction: column;
1265
+ gap: 2px;
1266
+ }
1267
+
1268
+ .opencode-node-text {
1269
+ color: #374151;
1270
+ font-weight: 500;
1271
+ overflow: hidden;
1272
+ text-overflow: ellipsis;
1273
+ white-space: nowrap;
1274
+ }
1275
+
1276
+ .opencode-node-file {
1277
+ color: #9ca3af;
1278
+ font-size: 11px;
1279
+ overflow: hidden;
1280
+ text-overflow: ellipsis;
1281
+ white-space: nowrap;
1282
+ }
1283
+
1284
+ .opencode-node-remove {
1285
+ width: 18px;
1286
+ height: 18px;
1287
+ border-radius: 4px;
1288
+ border: none;
1289
+ background: transparent;
1290
+ color: #9ca3af;
1291
+ cursor: pointer;
1292
+ display: flex;
1293
+ align-items: center;
1294
+ justify-content: center;
1295
+ font-size: 14px;
1296
+ transition: all 0.2s;
1297
+ flex-shrink: 0;
1298
+ }
1299
+
1300
+ .opencode-node-remove:hover {
1301
+ background: #ef4444;
1302
+ color: white;
1303
+ }
1304
+
1305
+ .opencode-dark .opencode-right-toolbar {
1306
+ background: #111827;
1307
+ border-left-color: #374151;
1308
+ }
1309
+
1310
+ .opencode-dark .opencode-select-btn {
1311
+ color: #9ca3af;
1312
+ border-bottom-color: #374151;
1313
+ }
1314
+
1315
+ .opencode-dark .opencode-select-btn:hover {
1316
+ background: #374151;
1317
+ color: #f3f4f6;
1318
+ }
1319
+
1320
+ .opencode-dark .opencode-selected-nodes:empty::before {
1321
+ color: #6b7280;
1322
+ }
1323
+
1324
+ .opencode-dark .opencode-selected-node {
1325
+ background: #1f2937;
1326
+ border-color: #374151;
1327
+ }
1328
+
1329
+ .opencode-dark .opencode-selected-node:hover {
1330
+ border-color: #3b82f6;
1331
+ }
1332
+
1333
+ .opencode-dark .opencode-node-text {
1334
+ color: #f3f4f6;
1335
+ }
1336
+
1337
+ .opencode-dark .opencode-node-file {
1338
+ color: #6b7280;
1339
+ }
1340
+
1341
+ .opencode-dark .opencode-node-remove {
1342
+ color: #6b7280;
1343
+ }
1344
+
1345
+ .opencode-dark .opencode-node-remove:hover {
1346
+ background: #ef4444;
1347
+ color: white;
1348
+ }
1349
+
1350
+ .opencode-dark .opencode-button {
1351
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1352
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.5);
1353
+ }
1354
+
1355
+ .opencode-notification {
1356
+ position: absolute;
1357
+ top: 20px;
1358
+ left: 50%;
1359
+ transform: translateX(-50%);
1360
+ padding: 12px 20px;
1361
+ background: #10b981;
1362
+ color: white;
1363
+ border-radius: 8px;
1364
+ font-size: 14px;
1365
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1366
+ animation: slideDown 0.3s ease;
1367
+ z-index: 10;
1368
+ }
1369
+
1370
+ @keyframes slideDown {
1371
+ from {
1372
+ transform: translateX(-50%) translateY(-100%);
1373
+ opacity: 0;
1374
+ }
1375
+ to {
1376
+ transform: translateX(-50%) translateY(0);
1377
+ opacity: 1;
1378
+ }
1379
+ }
1380
+
1381
+ .opencode-select-mode-hint {
1382
+ position: fixed;
1383
+ top: 20px;
1384
+ left: 50%;
1385
+ transform: translateX(-50%);
1386
+ padding: 10px 16px;
1387
+ background: #3b82f6;
1388
+ color: white;
1389
+ border-radius: 8px;
1390
+ font-size: 13px;
1391
+ box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
1392
+ z-index: 9999999;
1393
+ display: none;
1394
+ align-items: center;
1395
+ gap: 12px;
1396
+ }
1397
+
1398
+ .opencode-select-mode-hint.visible {
1399
+ display: flex;
1400
+ animation: slideDown 0.3s ease;
1401
+ }
1402
+
1403
+ .opencode-hint-shortcut {
1404
+ padding: 2px 6px;
1405
+ background: rgba(255, 255, 255, 0.2);
1406
+ border-radius: 4px;
1407
+ font-size: 12px;
1408
+ }
1409
+
1410
+ .opencode-selected-bubbles {
1411
+ position: absolute;
1412
+ bottom: 70px;
1413
+ right: 0;
1414
+ display: none;
1415
+ flex-direction: column;
1416
+ gap: 6px;
1417
+ max-width: 220px;
1418
+ max-height: 300px;
1419
+ overflow-y: auto;
1420
+ }
1421
+
1422
+ .opencode-selected-bubbles.visible {
1423
+ display: flex;
1424
+ }
1425
+
1426
+ .opencode-selected-bubble {
1427
+ display: flex;
1428
+ flex-direction: column;
1429
+ gap: 2px;
1430
+ padding: 8px 10px;
1431
+ background: white;
1432
+ border: 1px solid #e5e7eb;
1433
+ border-radius: 8px;
1434
+ font-size: 12px;
1435
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
1436
+ position: relative;
1437
+ }
1438
+
1439
+ .opencode-bubble-text {
1440
+ color: #374151;
1441
+ font-weight: 500;
1442
+ overflow: hidden;
1443
+ text-overflow: ellipsis;
1444
+ white-space: nowrap;
1445
+ }
1446
+
1447
+ .opencode-bubble-file {
1448
+ color: #9ca3af;
1449
+ font-size: 11px;
1450
+ overflow: hidden;
1451
+ text-overflow: ellipsis;
1452
+ white-space: nowrap;
1453
+ }
1454
+
1455
+ .opencode-bubble-remove {
1456
+ position: absolute;
1457
+ top: 4px;
1458
+ right: 4px;
1459
+ width: 16px;
1460
+ height: 16px;
1461
+ border-radius: 50%;
1462
+ border: none;
1463
+ background: transparent;
1464
+ color: #9ca3af;
1465
+ cursor: pointer;
1466
+ display: flex;
1467
+ align-items: center;
1468
+ justify-content: center;
1469
+ font-size: 12px;
1470
+ transition: all 0.2s;
1471
+ }
1472
+
1473
+ .opencode-bubble-remove:hover {
1474
+ background: #ef4444;
1475
+ color: white;
1476
+ }
1477
+
1478
+ .opencode-bubble-empty {
1479
+ padding: 8px 12px;
1480
+ background: white;
1481
+ border: 1px dashed #d1d5db;
1482
+ border-radius: 8px;
1483
+ color: #9ca3af;
1484
+ font-size: 12px;
1485
+ text-align: center;
1486
+ }
1487
+
1488
+ .opencode-dark .opencode-selected-bubble {
1489
+ background: #1f2937;
1490
+ border-color: #374151;
1491
+ }
1492
+
1493
+ .opencode-dark .opencode-bubble-text {
1494
+ color: #f3f4f6;
1495
+ }
1496
+
1497
+ .opencode-dark .opencode-bubble-file {
1498
+ color: #6b7280;
1499
+ }
1500
+
1501
+ .opencode-dark .opencode-bubble-remove {
1502
+ color: #6b7280;
1503
+ }
1504
+
1505
+ .opencode-dark .opencode-bubble-empty {
1506
+ background: #1f2937;
1507
+ border-color: #374151;
1508
+ color: #6b7280;
1509
+ }
1510
+
1511
+ @media (max-width: 768px) {
1512
+ .opencode-chat {
1513
+ width: calc(100vw - 40px);
1514
+ height: calc(100vh - 120px);
1515
+ }
1516
+ }
1517
+ `;
1518
+ }
1519
+ /**
1520
+ * 自动初始化挂件
1521
+ */
1522
+ function autoInit() {
1523
+ const script = document.currentScript || document.querySelector('script[data-opencode-config]');
1524
+ if (script) {
1525
+ const configBase64 = script.getAttribute('data-opencode-config');
1526
+ if (configBase64) {
1527
+ try {
1528
+ const config = JSON.parse(atob(configBase64));
1529
+ if (document.readyState === 'loading') {
1530
+ document.addEventListener('DOMContentLoaded', function () {
1531
+ initOpenCodeWidget(config);
1532
+ });
1533
+ }
1534
+ else {
1535
+ initOpenCodeWidget(config);
1536
+ }
1537
+ }
1538
+ catch (e) {
1539
+ console.error('[OpenCode Widget] Failed to parse config:', e);
1540
+ }
1541
+ }
1542
+ }
1543
+ }
1544
+ // 导出全局初始化函数
1545
+ window.initOpenCodeWidget = initOpenCodeWidget;
1546
+ // 自动初始化
1547
+ autoInit();
1548
+ })();
1549
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NsaWVudC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztHQUdHO0FBRUgsQ0FBQztJQUNDLFlBQVksQ0FBQTtJQUVaLDJCQUEyQjtJQUMzQixNQUFNLFdBQVcsR0FBRywwQkFBMEIsQ0FBQTtJQUU5Qyw2QkFBNkI7SUFDN0IsTUFBTSxxQkFBcUIsR0FBRyxnQ0FBZ0MsQ0FBQTtJQUU5RCxpQ0FBaUM7SUFDakMsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUE7SUFFakMsNkNBQTZDO0lBQzdDLE1BQU0sd0JBQXdCLEdBQUcsR0FBRyxDQUFBO0lBRXBDLGdDQUFnQztJQUNoQyxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUE7SUFFNUIsZ0NBQWdDO0lBQ2hDLE1BQU0scUJBQXFCLEdBQUcsSUFBSSxDQUFBO0lBRWxDOzs7Ozs7T0FNRztJQUVIOzs7Ozs7O09BT0c7SUFFSDs7Ozs7Ozs7O09BU0c7SUFFSDs7O09BR0c7SUFDSCxTQUFTLGtCQUFrQixDQUFDLE1BQU07UUFDaEMsSUFBSSxNQUFNLENBQUMsV0FBVyxDQUFDO1lBQUUsT0FBTTtRQUMvQixNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsSUFBSSxDQUFBO1FBRTFCLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsTUFBTSxDQUFBO1FBRS9FLDhCQUE4QjtRQUM5QixJQUFJLGNBQWMsR0FBRyxFQUFFLENBQUE7UUFFdkIsNEJBQTRCO1FBQzVCLElBQUksZ0JBQWdCLEdBQUcsRUFBRSxDQUFBO1FBRXpCLDhCQUE4QjtRQUM5QixJQUFJLGVBQWUsR0FBRyxDQUFDLElBQUksQ0FBQTtRQUUzQiw2QkFBNkI7UUFDN0IsSUFBSSxNQUFNLEdBQUcsS0FBSyxDQUFBO1FBRWxCOzs7O1dBSUc7UUFDSCxT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O3dCQUNOLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFBO29CQUM1QixDQUFDO2dCQUNILENBQUM7Z0JBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztvQkFDWCxPQUFPLENBQUMsS0FBSyxDQUFDLDJDQUEyQyxFQUFFLENBQUMsQ0FBQyxDQUFBO2dCQUMvRCxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsWUFBWTtJQUNaLE1BQU0sQ0FBQyxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQTtJQUU5QyxRQUFRO0lBQ1IsUUFBUSxFQUFFLENBQUE7QUFDWixDQUFDLENBQUMsRUFBRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAZmlsZW92ZXJ2aWV3IE9wZW5Db2RlIOaMguS7tuWuouaIt+err+iEmuacrFxuICogQGRlc2NyaXB0aW9uIOeUqOS6juWcqOa1j+iniOWZqOS4reaYvuekuiBPcGVuQ29kZSBBSSDliqnmiYvmjILku7ZcbiAqL1xuXG4oZnVuY3Rpb24oKSB7XG4gICd1c2Ugc3RyaWN0J1xuXG4gIC8qKiBAdHlwZSB7c3RyaW5nfSDliJ3lp4vljJbmoIforrAgKi9cbiAgY29uc3QgSU5JVF9NQVJLRVIgPSAnX19PUEVOQ09ERV9JTklUSUFMSVpFRF9fJ1xuXG4gIC8qKiBAdHlwZSB7c3RyaW5nfSDpgInkuK3lhYPntKDlrZjlgqjplK4gKi9cbiAgY29uc3QgU0VMRUNURURfRUxFTUVOVFNfS0VZID0gJ19fb3BlbmNvZGVfc2VsZWN0ZWRfZWxlbWVudHNfXydcblxuICAvKiogQHR5cGUge251bWJlcn0g5pyN5Yqh5Zmo5ZCM5q2l6Ze06ZqU77yI5q+r56eS77yJICovXG4gIGNvbnN0IFNFUlZFUl9TWU5DX0lOVEVSVkFMID0gMjAwMFxuXG4gIC8qKiBAdHlwZSB7bnVtYmVyfSDmo4Dmn6UgVnVlIEluc3BlY3RvciDpl7TpmpTvvIjmr6vnp5LvvIkgKi9cbiAgY29uc3QgSU5TUEVDVE9SX0NIRUNLX0lOVEVSVkFMID0gNTAwXG5cbiAgLyoqIEB0eXBlIHtudW1iZXJ9IOiHquWKqOaJk+W8gOW7tui/n++8iOavq+enku+8iSAqL1xuICBjb25zdCBBVVRPX09QRU5fREVMQVkgPSAxMDAwXG5cbiAgLyoqIEB0eXBlIHtudW1iZXJ9IOmAmuefpeaYvuekuuaXtumXtO+8iOavq+enku+8iSAqL1xuICBjb25zdCBOT1RJRklDQVRJT05fRFVSQVRJT04gPSAzMDAwXG5cbiAgLyoqXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IEhvdGtleUNvbmZpZ1xuICAgKiBAcHJvcGVydHkge2Jvb2xlYW59IGN0cmwgLSDmmK/lkKbpnIDopoEgQ3RybC9NZXRhIOmUrlxuICAgKiBAcHJvcGVydHkge2Jvb2xlYW59IHNoaWZ0IC0g5piv5ZCm6ZyA6KaBIFNoaWZ0IOmUrlxuICAgKiBAcHJvcGVydHkge2Jvb2xlYW59IGFsdCAtIOaYr+WQpumcgOimgSBBbHQg6ZSuXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBrZXkgLSDkuLvplK5cbiAgICovXG5cbiAgLyoqXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IFNlbGVjdGVkRWxlbWVudFxuICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBmaWxlUGF0aCAtIOaWh+S7tui3r+W+hFxuICAgKiBAcHJvcGVydHkge251bWJlcnxudWxsfSBsaW5lIC0g6KGM5Y+3XG4gICAqIEBwcm9wZXJ0eSB7bnVtYmVyfG51bGx9IGNvbHVtbiAtIOWIl+WPt1xuICAgKiBAcHJvcGVydHkge3N0cmluZ30gaW5uZXJUZXh0IC0g5YWD57Sg5YaF6YOo5paH5pysXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBkZXNjcmlwdGlvbiAtIOWFg+e0oOaPj+i/sO+8iOagh+etvuWQjSvpgInmi6nlmajvvIlcbiAgICovXG5cbiAgLyoqXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IFdpZGdldENvbmZpZ1xuICAgKiBAcHJvcGVydHkge3N0cmluZ30gd2ViVXJsIC0gV2ViIOacjeWKoSBVUkxcbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IHBvc2l0aW9uIC0g5oyC5Lu25L2N572uXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB0aGVtZSAtIOS4u+mimOaooeW8j1xuICAgKiBAcHJvcGVydHkge2Jvb2xlYW59IG9wZW4gLSDmmK/lkKboh6rliqjmiZPlvIBcbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IHNlc3Npb25VcmwgLSDkvJror50gVVJMXG4gICAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gbGF6eSAtIOaYr+WQpuaHkuWKoOi9vVxuICAgKiBAcHJvcGVydHkge3N0cmluZ30gaG90a2V5IC0g5b+r5o236ZSu6YWN572uXG4gICAqL1xuXG4gIC8qKlxuICAgKiDliJ3lp4vljJYgT3BlbkNvZGUg5oyC5Lu2XG4gICAqIEBwYXJhbSB7V2lkZ2V0Q29uZmlnfSBjb25maWcgLSDmjILku7bphY3nva5cbiAgICovXG4gIGZ1bmN0aW9uIGluaXRPcGVuQ29kZVdpZGdldChjb25maWcpIHtcbiAgICBpZiAod2luZG93W0lOSVRfTUFSS0VSXSkgcmV0dXJuXG4gICAgd2luZG93W0lOSVRfTUFSS0VSXSA9IHRydWVcblxuICAgIGNvbnN0IHsgd2ViVXJsLCBwb3NpdGlvbiwgdGhlbWUsIG9wZW4sIHNlc3Npb25VcmwsIGxhenksIGhvdGtleSwgY3dkIH0gPSBjb25maWdcblxuICAgIC8qKiBAdHlwZSB7c3RyaW5nfSDlvZPliY3pobXpnaIgVVJMICovXG4gICAgbGV0IGN1cnJlbnRQYWdlVXJsID0gJydcblxuICAgIC8qKiBAdHlwZSB7c3RyaW5nfSDlvZPliY3pobXpnaLmoIfpopggKi9cbiAgICBsZXQgY3VycmVudFBhZ2VUaXRsZSA9ICcnXG5cbiAgICAvKiogQHR5cGUge2Jvb2xlYW59IOacjeWKoeaYr+WQpuW3suWQr+WKqCAqL1xuICAgIGxldCBzZXJ2aWNlc1N0YXJ0ZWQgPSAhbGF6eVxuXG4gICAgLyoqIEB0eXBlIHtib29sZWFufSDmjILku7bmmK/lkKbmiZPlvIAgKi9cbiAgICBsZXQgaXNPcGVuID0gZmFsc2VcblxuICAgIC8qKlxuICAgICAqIOino+aekOW/q+aNt+mUruWtl+espuS4slxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBob3RrZXlTdHIgLSDlv6vmjbfplK7lrZfnrKbkuLLvvIzlpoIgJ2N0cmwraydcbiAgICAgKiBAcmV0dXJucyB7SG90a2V5Q29uZmlnfSDlv6vmjbfplK7phY3nva5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwYXJzZUhvdGtleShob3RrZXlTdHIpIHtcbiAgICAgIGlmICghaG90a2V5U3RyKSByZXR1cm4geyBjdHJsOiB0cnVlLCBzaGlmdDogZmFsc2UsIGFsdDogZmFsc2UsIGtleTogJ2snIH1cblxuICAgICAgY29uc3QgcGFydHMgPSBob3RrZXlTdHIudG9Mb3dlckNhc2UoKS5zcGxpdCgnKycpXG4gICAgICBjb25zdCBrZXkgPSBwYXJ0cy5wb3AoKVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjdHJsOiBwYXJ0cy5pbmNsdWRlcygnY3RybCcpIHx8IHBhcnRzLmluY2x1ZGVzKCdjbWQnKSB8fCBwYXJ0cy5pbmNsdWRlcygnbWV0YScpLFxuICAgICAgICBzaGlmdDogcGFydHMuaW5jbHVkZXMoJ3NoaWZ0JyksXG4gICAgICAgIGFsdDogcGFydHMuaW5jbHVkZXMoJ2FsdCcpLFxuICAgICAgICBrZXk6IGtleSB8fCAnaydcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogQHR5cGUge0hvdGtleUNvbmZpZ30g5Li75b+r5o236ZSu6YWN572uICovXG4gICAgY29uc3QgbWFpbkhvdGtleSA9IHBhcnNlSG90a2V5KGhvdGtleSlcblxuICAgIC8qKlxuICAgICAqIOajgOafpemUruebmOS6i+S7tuaYr+WQpuWMuemFjeW/q+aNt+mUrlxuICAgICAqIEBwYXJhbSB7S2V5Ym9hcmRFdmVudH0gZSAtIOmUruebmOS6i+S7tlxuICAgICAqIEBwYXJhbSB7SG90a2V5Q29uZmlnfSBob3RrZXlDb25maWcgLSDlv6vmjbfplK7phY3nva5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0g5piv5ZCm5Yy56YWNXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWF0Y2hIb3RrZXkoZSwgaG90a2V5Q29uZmlnKSB7XG4gICAgICBjb25zdCBjdHJsTWF0Y2ggPSBob3RrZXlDb25maWcuY3RybCA/IChlLmN0cmxLZXkgfHwgZS5tZXRhS2V5KSA6ICEoZS5jdHJsS2V5IHx8IGUubWV0YUtleSlcbiAgICAgIGNvbnN0IHNoaWZ0TWF0Y2ggPSBob3RrZXlDb25maWcuc2hpZnQgPyBlLnNoaWZ0S2V5IDogIWUuc2hpZnRLZXlcbiAgICAgIGNvbnN0IGFsdE1hdGNoID0gaG90a2V5Q29uZmlnLmFsdCA/IGUuYWx0S2V5IDogIWUuYWx0S2V5XG4gICAgICBjb25zdCBrZXlNYXRjaCA9IGUua2V5LnRvTG93ZXJDYXNlKCkgPT09IGhvdGtleUNvbmZpZy5rZXkudG9Mb3dlckNhc2UoKVxuXG4gICAgICByZXR1cm4gY3RybE1hdGNoICYmIHNoaWZ0TWF0Y2ggJiYgYWx0TWF0Y2ggJiYga2V5TWF0Y2hcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDku44gc2Vzc2lvblN0b3JhZ2Ug5Yqg6L296YCJ5Lit55qE5YWD57SgXG4gICAgICogQHJldHVybnMge1NlbGVjdGVkRWxlbWVudFtdfSDpgInkuK3nmoTlhYPntKDliJfooahcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsb2FkU2VsZWN0ZWRFbGVtZW50cygpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHN0b3JlZCA9IHNlc3Npb25TdG9yYWdlLmdldEl0ZW0oU0VMRUNURURfRUxFTUVOVFNfS0VZKVxuICAgICAgICBpZiAoc3RvcmVkKSB7XG4gICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2Uoc3RvcmVkKVxuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIOW/veeVpemUmeivr1xuICAgICAgfVxuICAgICAgcmV0dXJuIFtdXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog5L+d5a2Y6YCJ5Lit55qE5YWD57Sg5YiwIHNlc3Npb25TdG9yYWdlXG4gICAgICogQHBhcmFtIHtTZWxlY3RlZEVsZW1lbnRbXX0gZWxlbWVudHMgLSDpgInkuK3nmoTlhYPntKDliJfooahcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzYXZlU2VsZWN0ZWRFbGVtZW50cyhlbGVtZW50cykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgc2Vzc2lvblN0b3JhZ2Uuc2V0SXRlbShTRUxFQ1RFRF9FTEVNRU5UU19LRVksIEpTT04uc3RyaW5naWZ5KGVsZW1lbnRzKSlcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8g5b+955Wl6ZSZ6K+vXG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqIEB0eXBlIHtTZWxlY3RlZEVsZW1lbnRbXX0g6YCJ5Lit55qE5YWD57Sg5YiX6KGoICovXG4gICAgbGV0IHNlbGVjdGVkRWxlbWVudHMgPSBsb2FkU2VsZWN0ZWRFbGVtZW50cygpXG5cbiAgICAvKipcbiAgICAgKiDnoa7kv53mnI3liqHlt7LlkK/liqhcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxib29sZWFuPn0g5piv5ZCm5oiQ5Yqf5ZCv5YqoXG4gICAgICovXG4gICAgYXN5bmMgZnVuY3Rpb24gZW5zdXJlU2VydmljZXNTdGFydGVkKCkge1xuICAgICAgaWYgKHNlcnZpY2VzU3RhcnRlZCkgcmV0dXJuIHRydWVcblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgZmV0Y2goJy9fX29wZW5jb2RlX3N0YXJ0X18nKVxuICAgICAgICBjb25zdCBkYXRhID0gYXdhaXQgcmVzLmpzb24oKVxuICAgICAgICBpZiAoZGF0YS5zdWNjZXNzKSB7XG4gICAgICAgICAgc2VydmljZXNTdGFydGVkID0gdHJ1ZVxuICAgICAgICAgIGlmIChkYXRhLnNlc3Npb25VcmwgJiYgaWZyYW1lKSB7XG4gICAgICAgICAgICBpZnJhbWUuc3JjID0gZGF0YS5zZXNzaW9uVXJsXG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignW09wZW5Db2RlIFdpZGdldF0gRmFpbGVkIHRvIHN0YXJ0IHNlcnZpY2VzOicsIGUpXG4gICAgICB9XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDmm7TmlrDpobXpnaLkuIrkuIvmlodcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmb3JjZT1mYWxzZV0gLSDmmK/lkKblvLrliLbmm7TmlrBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1cGRhdGVDb250ZXh0KGZvcmNlID0gZmFsc2UpIHtcbiAgICAgIGlmICghc2VydmljZXNTdGFydGVkKSByZXR1cm5cblxuICAgICAgY29uc3QgbmV3VXJsID0gd2luZG93LmxvY2F0aW9uLmhyZWZcbiAgICAgIGNvbnN0IG5ld1RpdGxlID0gZG9jdW1lbnQudGl0bGVcblxuICAgICAgaWYgKGZvcmNlIHx8IG5ld1VybCAhPT0gY3VycmVudFBhZ2VVcmwgfHwgbmV3VGl0bGUgIT09IGN1cnJlbnRQYWdlVGl0bGUpIHtcbiAgICAgICAgY3VycmVudFBhZ2VVcmwgPSBuZXdVcmxcbiAgICAgICAgY3VycmVudFBhZ2VUaXRsZSA9IG5ld1RpdGxlXG5cbiAgICAgICAgZmV0Y2goJy9fX29wZW5jb2RlX2NvbnRleHRfXycsIHtcbiAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICBoZWFkZXJzOiB7ICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicgfSxcbiAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7IHVybDogbmV3VXJsLCB0aXRsZTogbmV3VGl0bGUsIHNlbGVjdGVkRWxlbWVudHMgfSlcbiAgICAgICAgfSkuY2F0Y2goKCkgPT4ge30pXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8g55uR5ZCs6Lev55Sx5Y+Y5YyWXG4gICAgY29uc3Qgb3JpZ2luYWxQdXNoU3RhdGUgPSBoaXN0b3J5LnB1c2hTdGF0ZVxuICAgIGNvbnN0IG9yaWdpbmFsUmVwbGFjZVN0YXRlID0gaGlzdG9yeS5yZXBsYWNlU3RhdGVcblxuICAgIGhpc3RvcnkucHVzaFN0YXRlID0gZnVuY3Rpb24oLi4uYXJncykge1xuICAgICAgb3JpZ2luYWxQdXNoU3RhdGUuYXBwbHkodGhpcywgYXJncylcbiAgICAgIHNldFRpbWVvdXQodXBkYXRlQ29udGV4dCwgMClcbiAgICB9XG5cbiAgICBoaXN0b3J5LnJlcGxhY2VTdGF0ZSA9IGZ1bmN0aW9uKC4uLmFyZ3MpIHtcbiAgICAgIG9yaWdpbmFsUmVwbGFjZVN0YXRlLmFwcGx5KHRoaXMsIGFyZ3MpXG4gICAgICBzZXRUaW1lb3V0KHVwZGF0ZUNvbnRleHQsIDApXG4gICAgfVxuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3BvcHN0YXRlJywgKCkgPT4gc2V0VGltZW91dCh1cGRhdGVDb250ZXh0LCAwKSlcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignaGFzaGNoYW5nZScsICgpID0+IHNldFRpbWVvdXQodXBkYXRlQ29udGV4dCwgMCkpXG5cbiAgICAvLyDnm5HlkKzmoIfpopjlj5jljJZcbiAgICBjb25zdCB0aXRsZU9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoKCkgPT4ge1xuICAgICAgaWYgKGRvY3VtZW50LnRpdGxlICE9PSBjdXJyZW50UGFnZVRpdGxlKSB7XG4gICAgICAgIHVwZGF0ZUNvbnRleHQoKVxuICAgICAgfVxuICAgIH0pXG5cbiAgICBpZiAoZG9jdW1lbnQuaGVhZCkge1xuICAgICAgdGl0bGVPYnNlcnZlci5vYnNlcnZlKGRvY3VtZW50LmhlYWQsIHsgY2hpbGRMaXN0OiB0cnVlLCBzdWJ0cmVlOiB0cnVlIH0pXG4gICAgfVxuXG4gICAgaWYgKHNlcnZpY2VzU3RhcnRlZCkge1xuICAgICAgdXBkYXRlQ29udGV4dCh0cnVlKVxuICAgIH1cblxuICAgIC8qKiBAdHlwZSB7c3RyaW5nfSBpZnJhbWUgVVJMICovXG4gICAgY29uc3QgaWZyYW1lVXJsID0gc2Vzc2lvblVybCB8fCB3ZWJVcmxcblxuICAgIC8vIOWIm+W7uuagt+W8j1xuICAgIGNvbnN0IHN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3R5bGUnKVxuICAgIHN0eWxlLnRleHRDb250ZW50ID0gYnVpbGRXaWRnZXRTdHlsZXMoKVxuICAgIGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc3R5bGUpXG5cbiAgICAvLyDliJvlu7rlrrnlmahcbiAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgIGNvbnRhaW5lci5jbGFzc05hbWUgPSBgb3BlbmNvZGUtd2lkZ2V0ICR7cG9zaXRpb259YFxuXG4gICAgLy8g5Yib5bu65oyJ6ZKuXG4gICAgY29uc3QgYnV0dG9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJylcbiAgICBidXR0b24uY2xhc3NOYW1lID0gJ29wZW5jb2RlLWJ1dHRvbidcbiAgICBidXR0b24uaW5uZXJIVE1MID0gYFxuICAgICAgPHN2ZyB0PVwiMTc3NTQwMjU5OTU4MFwiIGNsYXNzPVwiaWNvblwiIHZpZXdCb3g9XCIwIDAgMTAyNCAxMDI0XCIgdmVyc2lvbj1cIjEuMVwiIHhtbG5zPVwiIGh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIFwiIHAtaWQ9XCI1MzkwXCIgeG1sbnM6eGxpbms9XCIgaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayBcIiB3aWR0aD1cIjIwMFwiIGhlaWdodD1cIjIwMFwiPjxwYXRoIGQ9XCJNNTEyIDk4MS4zM0g4NS4zNGMtMTUuODUgMC0zMC4zOC04Ljc3LTM3Ljc3LTIyLjgxYTQyLjYyNCA0Mi42MjQgMCAwIDEgMi42LTQ0LjAyTDEzNSA3OTEuMDhDNzUuMjUgNzEwLjUgNDIuNjcgNjEyLjYgNDIuNjcgNTEyIDQyLjY3IDI1My4yMSAyNTMuMjEgNDIuNjcgNTEyIDQyLjY3Uzk4MS4zNCAyNTMuMjEgOTgxLjM0IDUxMiA3NzAuOCA5ODEuMzMgNTEyIDk4MS4zM3pNMTY2LjQ0IDg5Nkg1MTJjMjExLjczIDAgMzg0LTE3Mi4yNyAzODQtMzg0UzcyMy43MyAxMjggNTEyIDEyOCAxMjggMzAwLjI3IDEyOCA1MTJjMCA5MS4yOSAzMi44MyAxNzkuOSA5Mi40NiAyNDkuNDYgMTIuNTggMTQuNjkgMTMuNzMgMzYgMi43NyA1MS45NEwxNjYuNDQgODk2elwiIGZpbGw9XCJ3aGl0ZVwiIHAtaWQ9XCI1MzkxXCI+PC9wYXRoPjxwYXRoIGQ9XCJNMzg0IDQ0OG0tNjQgMGE2NCA2NCAwIDEgMCAxMjggMCA2NCA2NCAwIDEgMC0xMjggMFpcIiBmaWxsPVwid2hpdGVcIiBwLWlkPVwiNTM5MlwiPjwvcGF0aD48cGF0aCBkPVwiTTY0MCA0NDhtLTY0IDBhNjQgNjQgMCAxIDAgMTI4IDAgNjQgNjQgMCAxIDAtMTI4IDBaXCIgZmlsbD1cIndoaXRlXCIgcC1pZD1cIjUzOTNcIj48L3BhdGg+PC9zdmc+XG4gICAgYFxuICAgIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCAnT3BlbiBBSSBBc3Npc3RhbnQnKVxuXG4gICAgLy8g5Yib5bu66IGK5aSp6Z2i5p2/XG4gICAgY29uc3QgY2hhdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpXG4gICAgY2hhdC5jbGFzc05hbWUgPSAnb3BlbmNvZGUtY2hhdCdcblxuICAgIC8vIOWIm+W7uuS8muivneWIl+ihqFxuICAgIGNvbnN0IHNlc3Npb25MaXN0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JylcbiAgICBzZXNzaW9uTGlzdC5jbGFzc05hbWUgPSAnb3BlbmNvZGUtc2Vzc2lvbi1saXN0IGNvbGxhcHNlZCdcblxuICAgIC8vIOWIm+W7uuaKmOWPoOaMiemSrlxuICAgIGNvbnN0IHRvZ2dsZUJ0biA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2J1dHRvbicpXG4gICAgdG9nZ2xlQnRuLmNsYXNzTmFtZSA9ICdvcGVuY29kZS1zZXNzaW9uLXRvZ2dsZSdcbiAgICB0b2dnbGVCdG4uaW5uZXJIVE1MID0gYFxuICAgICAgPHN2ZyB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiPlxuICAgICAgICA8cGF0aCBkPVwiTTQgNmgxNk00IDEyaDE2TTQgMThoMTZcIiBzdHJva2U9XCJjdXJyZW50Q29sb3JcIiBzdHJva2Utd2lkdGg9XCIyXCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiLz5cbiAgICAgIDwvc3ZnPlxuICAgIGBcbiAgICB0b2dnbGVCdG4udGl0bGUgPSAn5bGV5byA5Lya6K+d5YiX6KGoJ1xuXG4gICAgLy8g5Yib5bu65Lya6K+d5YiX6KGo5aS06YOoXG4gICAgY29uc3Qgc2Vzc2lvbkxpc3RIZWFkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgIHNlc3Npb25MaXN0SGVhZGVyLmNsYXNzTmFtZSA9ICdvcGVuY29kZS1zZXNzaW9uLWxpc3QtaGVhZGVyJ1xuICAgIHNlc3Npb25MaXN0SGVhZGVyLmlubmVySFRNTCA9IGBcbiAgICAgIDxzcGFuPuS8muivneWIl+ihqDwvc3Bhbj5cbiAgICAgIDxidXR0b24gY2xhc3M9XCJvcGVuY29kZS1uZXctc2Vzc2lvbi1idG5cIiB0aXRsZT1cIuaWsOW7uuS8muivnVwiPis8L2J1dHRvbj5cbiAgICBgXG5cbiAgICAvLyDliJvlu7rkvJror53liJfooajlhoXlrrlcbiAgICBjb25zdCBzZXNzaW9uTGlzdENvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgIHNlc3Npb25MaXN0Q29udGVudC5jbGFzc05hbWUgPSAnb3BlbmNvZGUtc2Vzc2lvbi1saXN0LWNvbnRlbnQnXG5cbiAgICBzZXNzaW9uTGlzdC5hcHBlbmRDaGlsZCh0b2dnbGVCdG4pXG4gICAgc2Vzc2lvbkxpc3QuYXBwZW5kQ2hpbGQoc2Vzc2lvbkxpc3RIZWFkZXIpXG4gICAgc2Vzc2lvbkxpc3QuYXBwZW5kQ2hpbGQoc2Vzc2lvbkxpc3RDb250ZW50KVxuXG4gICAgLy8g5oqY5Y+gL+WxleW8gOS8muivneWIl+ihqFxuICAgIGxldCBpc1Nlc3Npb25MaXN0Q29sbGFwc2VkID0gdHJ1ZVxuICAgIGZ1bmN0aW9uIHRvZ2dsZVNlc3Npb25MaXN0KCkge1xuICAgICAgaXNTZXNzaW9uTGlzdENvbGxhcHNlZCA9ICFpc1Nlc3Npb25MaXN0Q29sbGFwc2VkXG4gICAgICBzZXNzaW9uTGlzdC5jbGFzc0xpc3QudG9nZ2xlKCdjb2xsYXBzZWQnLCBpc1Nlc3Npb25MaXN0Q29sbGFwc2VkKVxuICAgICAgdG9nZ2xlQnRuLnRpdGxlID0gaXNTZXNzaW9uTGlzdENvbGxhcHNlZCA/ICflsZXlvIDkvJror53liJfooagnIDogJ+aKmOWPoOS8muivneWIl+ihqCdcbiAgICB9XG4gICAgdG9nZ2xlQnRuLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdG9nZ2xlU2Vzc2lvbkxpc3QpXG5cbiAgICAvLyDliJvlu7ogaWZyYW1lIOWuueWZqFxuICAgIGNvbnN0IGlmcmFtZUNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpXG4gICAgaWZyYW1lQ29udGFpbmVyLmNsYXNzTmFtZSA9ICdvcGVuY29kZS1pZnJhbWUtY29udGFpbmVyJ1xuXG4gICAgLy8g5Yib5bu65Yqg6L295oyH56S65ZmoXG4gICAgY29uc3QgbG9hZGluZ092ZXJsYXkgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgIGxvYWRpbmdPdmVybGF5LmNsYXNzTmFtZSA9ICdvcGVuY29kZS1sb2FkaW5nLW92ZXJsYXknXG4gICAgbG9hZGluZ092ZXJsYXkuaW5uZXJIVE1MID0gYFxuICAgICAgPGRpdiBjbGFzcz1cIm9wZW5jb2RlLWxvYWRpbmctc3Bpbm5lclwiPjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cIm9wZW5jb2RlLWxvYWRpbmctdGV4dFwiPuWKoOi9veS4rS4uLjwvZGl2PlxuICAgIGBcblxuICAgIC8vIOWIm+W7uiBpZnJhbWVcbiAgICBjb25zdCBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKVxuICAgIGlmcmFtZS5jbGFzc05hbWUgPSAnb3BlbmNvZGUtaWZyYW1lJ1xuICAgIGlmcmFtZS5zcmMgPSBzZXJ2aWNlc1N0YXJ0ZWQgPyBpZnJhbWVVcmwgOiAnYWJvdXQ6YmxhbmsnXG4gICAgaWZyYW1lLmFsbG93ID0gJ2NsaXBib2FyZC13cml0ZTsgY2xpcGJvYXJkLXJlYWQnXG4gICAgaWZyYW1lLnJlZmVycmVyUG9saWN5ID0gJ29yaWdpbidcblxuICAgIGlmcmFtZS5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgIGlmIChzZXJ2aWNlc1N0YXJ0ZWQpIHtcbiAgICAgICAgdXBkYXRlQ29udGV4dCgpXG4gICAgICAgIGxvYWRTZXNzaW9ucygpXG4gICAgICB9XG4gICAgICBoaWRlTG9hZGluZygpXG4gICAgfVxuXG4gICAgaWZyYW1lQ29udGFpbmVyLmFwcGVuZENoaWxkKGxvYWRpbmdPdmVybGF5KVxuICAgIGlmcmFtZUNvbnRhaW5lci5hcHBlbmRDaGlsZChpZnJhbWUpXG5cbiAgICAvLyDliJvlu7rlj7Pkvqflt6XlhbfmoI9cbiAgICBjb25zdCByaWdodFRvb2xiYXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgIHJpZ2h0VG9vbGJhci5jbGFzc05hbWUgPSBgb3BlbmNvZGUtcmlnaHQtdG9vbGJhciR7c2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggPT09IDAgPyAnIGNvbGxhcHNlZCcgOiAnJ31gXG5cbiAgICAvLyDliJvlu7rlhYPntKDpgInmi6nmjInpkq5cbiAgICBjb25zdCBzZWxlY3RCdXR0b24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdidXR0b24nKVxuICAgIHNlbGVjdEJ1dHRvbi5jbGFzc05hbWUgPSAnb3BlbmNvZGUtc2VsZWN0LWJ0bidcbiAgICBzZWxlY3RCdXR0b24uaW5uZXJIVE1MID0gYFxuICAgICAgPHN2ZyB2aWV3Qm94PVwiMCAwIDEwMjQgMTAyNFwiIHdpZHRoPVwiMThcIiBoZWlnaHQ9XCIxOFwiIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIj5cbiAgICAgICAgPHBhdGggZmlsbD1cImN1cnJlbnRDb2xvclwiIGQ9XCJNNTEyIDg5NmEzODQgMzg0IDAgMSAwIDAtNzY4IDM4NCAzODQgMCAwIDAgMCA3NjhtMCA2NGE0NDggNDQ4IDAgMSAxIDAtODk2IDQ0OCA0NDggMCAwIDEgMCA4OTZcIj48L3BhdGg+PHBhdGggZmlsbD1cImN1cnJlbnRDb2xvclwiIGQ9XCJNNTEyIDk2YTMyIDMyIDAgMCAxIDMyIDMydjE5MmEzMiAzMiAwIDAgMS02NCAwVjEyOGEzMiAzMiAwIDAgMSAzMi0zMm0wIDU3NmEzMiAzMiAwIDAgMSAzMiAzMnYxOTJhMzIgMzIgMCAxIDEtNjQgMFY3MDRhMzIgMzIgMCAwIDEgMzItMzJNOTYgNTEyYTMyIDMyIDAgMCAxIDMyLTMyaDE5MmEzMiAzMiAwIDAgMSAwIDY0SDEyOGEzMiAzMiAwIDAgMS0zMi0zMm01NzYgMGEzMiAzMiAwIDAgMSAzMi0zMmgxOTJhMzIgMzIgMCAxIDEgMCA2NEg3MDRhMzIgMzIgMCAwIDEtMzItMzJcIj48L3BhdGg+XG4gICAgICA8L3N2Zz5cbiAgICBgXG4gICAgc2VsZWN0QnV0dG9uLnRpdGxlID0gJ+mAieaLqemhtemdouWFg+e0oCdcblxuICAgIC8vIOWIm+W7uuW3sumAieiKgueCueWuueWZqFxuICAgIGNvbnN0IHNlbGVjdGVkTm9kZXNDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgIHNlbGVjdGVkTm9kZXNDb250YWluZXIuY2xhc3NOYW1lID0gJ29wZW5jb2RlLXNlbGVjdGVkLW5vZGVzJ1xuXG4gICAgcmlnaHRUb29sYmFyLmFwcGVuZENoaWxkKHNlbGVjdEJ1dHRvbilcbiAgICByaWdodFRvb2xiYXIuYXBwZW5kQ2hpbGQoc2VsZWN0ZWROb2Rlc0NvbnRhaW5lcilcblxuICAgIC8vIOWIm+W7uumAieaLqeaooeW8j+W4uOmpu+aPkOekuu+8iOWbuuWumuWIsOmhtemdoumhtumDqO+8iVxuICAgIGNvbnN0IHNlbGVjdE1vZGVIaW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JylcbiAgICBzZWxlY3RNb2RlSGludC5jbGFzc05hbWUgPSAnb3BlbmNvZGUtc2VsZWN0LW1vZGUtaGludCdcbiAgICBzZWxlY3RNb2RlSGludC5pbm5lckhUTUwgPSBgXG4gICAgICA8c3Bhbj7wn46vIOmAieaLqeaooeW8j+W3suW8gOWQryAtIOeCueWHu+WFg+e0oOi/m+ihjOmAieaLqTwvc3Bhbj5cbiAgICAgIDxzcGFuIGNsYXNzPVwib3BlbmNvZGUtaGludC1zaG9ydGN1dFwiPuaMiSBFU0Mg6YCA5Ye6PC9zcGFuPlxuICAgIGBcblxuICAgIC8vIOWIm+W7uuW3sumAieiKgueCueawlOazoeWuueWZqO+8iOawlOazoeaMiemSruS4iuaWue+8iVxuICAgIGNvbnN0IHNlbGVjdGVkQnViYmxlcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpXG4gICAgc2VsZWN0ZWRCdWJibGVzLmNsYXNzTmFtZSA9ICdvcGVuY29kZS1zZWxlY3RlZC1idWJibGVzJ1xuXG4gICAgY2hhdC5hcHBlbmRDaGlsZChzZXNzaW9uTGlzdClcbiAgICBjaGF0LmFwcGVuZENoaWxkKGlmcmFtZUNvbnRhaW5lcilcbiAgICBjaGF0LmFwcGVuZENoaWxkKHJpZ2h0VG9vbGJhcilcblxuICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChidXR0b24pXG4gICAgY29udGFpbmVyLmFwcGVuZENoaWxkKHNlbGVjdGVkQnViYmxlcylcbiAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQoY2hhdClcbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGNvbnRhaW5lcilcbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHNlbGVjdE1vZGVIaW50KVxuXG4gICAgaWYgKHNlbGVjdGVkRWxlbWVudHMubGVuZ3RoID4gMCkge1xuICAgICAgcmVuZGVyU2VsZWN0ZWROb2RlcygpXG4gICAgfVxuXG4gICAgLyoqIEB0eXBlIHtBcnJheX0g5Lya6K+d5YiX6KGoICovXG4gICAgbGV0IHNlc3Npb25zID0gW11cblxuICAgIC8qKiBAdHlwZSB7c3RyaW5nfG51bGx9IOW9k+WJjeS8muivnSBJRCAqL1xuICAgIGxldCBjdXJyZW50U2Vzc2lvbklkID0gbnVsbFxuXG4gICAgLyoqXG4gICAgICog5LuOIFVSTCDkuK3mj5Dlj5bkvJror50gSURcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBleHRyYWN0U2Vzc2lvbklkKHVybCkge1xuICAgICAgaWYgKCF1cmwpIHJldHVybiBudWxsXG4gICAgICBjb25zdCBtYXRjaCA9IHVybC5tYXRjaCgvXFwvc2Vzc2lvblxcLyhbXi8/XSspLylcbiAgICAgIHJldHVybiBtYXRjaCA/IG1hdGNoWzFdIDogbnVsbFxuICAgIH1cblxuICAgIC8vIOS7juWIneWniyBVUkwg5Lit5o+Q5Y+W5Lya6K+dIElEXG4gICAgY3VycmVudFNlc3Npb25JZCA9IGV4dHJhY3RTZXNzaW9uSWQoc2Vzc2lvblVybClcblxuICAgIC8qKlxuICAgICAqIOaYvuekuuWKoOi9veeKtuaAgVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNob3dMb2FkaW5nKCkge1xuICAgICAgbG9hZGluZ092ZXJsYXkuY2xhc3NMaXN0LmFkZCgndmlzaWJsZScpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog6ZqQ6JeP5Yqg6L2954q25oCBXG4gICAgICovXG4gICAgZnVuY3Rpb24gaGlkZUxvYWRpbmcoKSB7XG4gICAgICBsb2FkaW5nT3ZlcmxheS5jbGFzc0xpc3QucmVtb3ZlKCd2aXNpYmxlJylcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDliqDovb3kvJror53liJfooahcbiAgICAgKi9cbiAgICBhc3luYyBmdW5jdGlvbiBsb2FkU2Vzc2lvbnMoKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKCcvX19vcGVuY29kZV9zZXNzaW9uc19fJylcbiAgICAgICAgc2Vzc2lvbnMgPSBhd2FpdCByZXNwb25zZS5qc29uKClcbiAgICAgICAgcmVuZGVyU2Vzc2lvbkxpc3QoKVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gbG9hZCBzZXNzaW9uczonLCBlKVxuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIOa4suafk+S8muivneWIl+ihqFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlbmRlclNlc3Npb25MaXN0KCkge1xuICAgICAgc2Vzc2lvbkxpc3RDb250ZW50LmlubmVySFRNTCA9ICcnXG4gICAgICBcbiAgICAgIGNvbnN0IGN1cnJlbnRQcm9qZWN0U2Vzc2lvbnMgPSBzZXNzaW9ucy5maWx0ZXIoc2Vzc2lvbiA9PiBzZXNzaW9uLmRpcmVjdG9yeSA9PT0gY3dkKVxuICAgICAgXG4gICAgICBjdXJyZW50UHJvamVjdFNlc3Npb25zLmZvckVhY2goc2Vzc2lvbiA9PiB7XG4gICAgICAgIGNvbnN0IGl0ZW0gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgICAgICBpdGVtLmNsYXNzTmFtZSA9ICdvcGVuY29kZS1zZXNzaW9uLWl0ZW0nXG4gICAgICAgIGlmIChzZXNzaW9uLmlkID09PSBjdXJyZW50U2Vzc2lvbklkKSB7XG4gICAgICAgICAgaXRlbS5jbGFzc0xpc3QuYWRkKCdhY3RpdmUnKVxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBjb25zdCBoZWFkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgICAgICBoZWFkZXIuY2xhc3NOYW1lID0gJ29wZW5jb2RlLXNlc3Npb24taGVhZGVyJ1xuICAgICAgICBcbiAgICAgICAgY29uc3QgdGl0bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgICAgICB0aXRsZS5jbGFzc05hbWUgPSAnb3BlbmNvZGUtc2Vzc2lvbi10aXRsZSdcbiAgICAgICAgdGl0bGUudGV4dENvbnRlbnQgPSBzZXNzaW9uLnRpdGxlIHx8ICfmlrDkvJror50nXG4gICAgICAgIFxuICAgICAgICBjb25zdCBkZWxldGVCdG4gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdidXR0b24nKVxuICAgICAgICBkZWxldGVCdG4uY2xhc3NOYW1lID0gJ29wZW5jb2RlLXNlc3Npb24tZGVsZXRlLWJ0bidcbiAgICAgICAgZGVsZXRlQnRuLmlubmVySFRNTCA9ICfDlydcbiAgICAgICAgZGVsZXRlQnRuLnRpdGxlID0gJ+WIoOmZpOS8muivnSdcbiAgICAgICAgZGVsZXRlQnRuLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKGUpID0+IHtcbiAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpXG4gICAgICAgICAgY29uZmlybURlbGV0ZVNlc3Npb24oc2Vzc2lvbilcbiAgICAgICAgfSlcbiAgICAgICAgXG4gICAgICAgIGhlYWRlci5hcHBlbmRDaGlsZCh0aXRsZSlcbiAgICAgICAgaGVhZGVyLmFwcGVuZENoaWxkKGRlbGV0ZUJ0bilcbiAgICAgICAgXG4gICAgICAgIGNvbnN0IG1ldGEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKVxuICAgICAgICBtZXRhLmNsYXNzTmFtZSA9ICdvcGVuY29kZS1zZXNzaW9uLW1ldGEnXG4gICAgICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZShzZXNzaW9uLnRpbWUudXBkYXRlZClcbiAgICAgICAgbWV0YS50ZXh0Q29udGVudCA9IGRhdGUudG9Mb2NhbGVEYXRlU3RyaW5nKCkgKyAnICcgKyBkYXRlLnRvTG9jYWxlVGltZVN0cmluZygpXG4gICAgICAgIFxuICAgICAgICBpdGVtLmFwcGVuZENoaWxkKGhlYWRlcilcbiAgICAgICAgaXRlbS5hcHBlbmRDaGlsZChtZXRhKVxuICAgICAgICBcbiAgICAgICAgaXRlbS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHtcbiAgICAgICAgICBzd2l0Y2hTZXNzaW9uKHNlc3Npb24pXG4gICAgICAgIH0pXG4gICAgICAgIFxuICAgICAgICBzZXNzaW9uTGlzdENvbnRlbnQuYXBwZW5kQ2hpbGQoaXRlbSlcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog5YiH5o2i5Lya6K+dXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3dpdGNoU2Vzc2lvbihzZXNzaW9uKSB7XG4gICAgICBpZiAoc2Vzc2lvbi5pZCA9PT0gY3VycmVudFNlc3Npb25JZCkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICAgIFxuICAgICAgY3VycmVudFNlc3Npb25JZCA9IHNlc3Npb24uaWRcbiAgICAgIGNvbnN0IGVuY29kZWREaXIgPSBidG9hKGN3ZClcbiAgICAgIGNvbnN0IGJhc2VVcmwgPSBpZnJhbWVVcmwuc3BsaXQoJy8nKS5zbGljZSgwLCAzKS5qb2luKCcvJylcbiAgICAgIHNob3dMb2FkaW5nKClcbiAgICAgIGlmcmFtZS5zcmMgPSBgJHtiYXNlVXJsfS8ke2VuY29kZWREaXJ9L3Nlc3Npb24vJHtzZXNzaW9uLmlkfWBcbiAgICAgIHJlbmRlclNlc3Npb25MaXN0KClcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDliJvlu7rmlrDkvJror51cbiAgICAgKi9cbiAgICBhc3luYyBmdW5jdGlvbiBjcmVhdGVOZXdTZXNzaW9uKCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCgnL19fb3BlbmNvZGVfc2Vzc2lvbnNfXycsIHtcbiAgICAgICAgICBtZXRob2Q6ICdQT1NUJ1xuICAgICAgICB9KVxuICAgICAgICBjb25zdCBuZXdTZXNzaW9uID0gYXdhaXQgcmVzcG9uc2UuanNvbigpXG4gICAgICAgIHNlc3Npb25zLnVuc2hpZnQobmV3U2Vzc2lvbilcbiAgICAgICAgc3dpdGNoU2Vzc2lvbihuZXdTZXNzaW9uKVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gY3JlYXRlIHNlc3Npb246JywgZSlcbiAgICAgICAgc2hvd05vdGlmaWNhdGlvbign5Yib5bu65Lya6K+d5aSx6LSlJylcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDnoa7orqTliKDpmaTkvJror51cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb25maXJtRGVsZXRlU2Vzc2lvbihzZXNzaW9uKSB7XG4gICAgICBjb25zdCBjb25maXJtZWQgPSBjb25maXJtKGDnoa7lrpropoHliKDpmaTkvJror50gXCIke3Nlc3Npb24udGl0bGUgfHwgJ+aWsOS8muivnSd9XCIg5ZCX77yfYClcbiAgICAgIGlmIChjb25maXJtZWQpIHtcbiAgICAgICAgZGVsZXRlU2Vzc2lvbihzZXNzaW9uKVxuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIOWIoOmZpOS8muivnVxuICAgICAqL1xuICAgIGFzeW5jIGZ1bmN0aW9uIGRlbGV0ZVNlc3Npb24oc2Vzc2lvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChgL19fb3BlbmNvZGVfc2Vzc2lvbnNfXz9pZD0ke3Nlc3Npb24uaWR9YCwge1xuICAgICAgICAgIG1ldGhvZDogJ0RFTEVURSdcbiAgICAgICAgfSlcbiAgICAgICAgXG4gICAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RlbGV0ZSBmYWlsZWQnKVxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBzZXNzaW9ucyA9IHNlc3Npb25zLmZpbHRlcihzID0+IHMuaWQgIT09IHNlc3Npb24uaWQpXG4gICAgICAgIFxuICAgICAgICBpZiAoc2Vzc2lvbi5pZCA9PT0gY3VycmVudFNlc3Npb25JZCkge1xuICAgICAgICAgIGNvbnN0IHJlbWFpbmluZ1Nlc3Npb25zID0gc2Vzc2lvbnMuZmlsdGVyKHMgPT4gcy5kaXJlY3RvcnkgPT09IGN3ZClcbiAgICAgICAgICBpZiAocmVtYWluaW5nU2Vzc2lvbnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgc3dpdGNoU2Vzc2lvbihyZW1haW5pbmdTZXNzaW9uc1swXSlcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY3VycmVudFNlc3Npb25JZCA9IG51bGxcbiAgICAgICAgICAgIGlmcmFtZS5zcmMgPSAnYWJvdXQ6YmxhbmsnXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICByZW5kZXJTZXNzaW9uTGlzdCgpXG4gICAgICAgIHNob3dOb3RpZmljYXRpb24oJ+S8muivneW3suWIoOmZpCcpXG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBkZWxldGUgc2Vzc2lvbjonLCBlKVxuICAgICAgICBzaG93Tm90aWZpY2F0aW9uKCfliKDpmaTkvJror53lpLHotKUnKVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIOe7keWumuaWsOW7uuS8muivneaMiemSrlxuICAgIHNlc3Npb25MaXN0SGVhZGVyLnF1ZXJ5U2VsZWN0b3IoJy5vcGVuY29kZS1uZXctc2Vzc2lvbi1idG4nKS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGNyZWF0ZU5ld1Nlc3Npb24pXG5cbiAgICAvKipcbiAgICAgKiDlupTnlKjkuLvpophcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhcHBseVRoZW1lKCkge1xuICAgICAgaWYgKHRoZW1lID09PSAnYXV0bycpIHtcbiAgICAgICAgY29uc3QgcHJlZmVyc0RhcmsgPSB3aW5kb3cubWF0Y2hNZWRpYSgnKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKScpLm1hdGNoZXNcbiAgICAgICAgY29udGFpbmVyLmNsYXNzTGlzdC50b2dnbGUoJ29wZW5jb2RlLWRhcmsnLCBwcmVmZXJzRGFyaylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnRhaW5lci5jbGFzc0xpc3QudG9nZ2xlKCdvcGVuY29kZS1kYXJrJywgdGhlbWUgPT09ICdkYXJrJylcbiAgICAgIH1cbiAgICB9XG5cbiAgICBhcHBseVRoZW1lKClcblxuICAgIGlmICh0aGVtZSA9PT0gJ2F1dG8nKSB7XG4gICAgICB3aW5kb3cubWF0Y2hNZWRpYSgnKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKScpLmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIGFwcGx5VGhlbWUpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog5YiH5o2i5oyC5Lu25pi+56S654q25oCBXG4gICAgICovXG4gICAgYXN5bmMgZnVuY3Rpb24gdG9nZ2xlKCkge1xuICAgICAgaWYgKGxhenkgJiYgIXNlcnZpY2VzU3RhcnRlZCkge1xuICAgICAgICBidXR0b24uY2xhc3NMaXN0LmFkZCgnbG9hZGluZycpXG4gICAgICAgIGNvbnN0IHN0YXJ0ZWQgPSBhd2FpdCBlbnN1cmVTZXJ2aWNlc1N0YXJ0ZWQoKVxuICAgICAgICBidXR0b24uY2xhc3NMaXN0LnJlbW92ZSgnbG9hZGluZycpXG4gICAgICAgIGlmICghc3RhcnRlZCkge1xuICAgICAgICAgIHNob3dOb3RpZmljYXRpb24oJ+acjeWKoeWQr+WKqOWksei0pe+8jOivt+ajgOafpeaOp+WItuWPsCcpXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaXNPcGVuID0gIWlzT3BlblxuICAgICAgY2hhdC5jbGFzc0xpc3QudG9nZ2xlKCdvcGVuJywgaXNPcGVuKVxuICAgICAgYnV0dG9uLmNsYXNzTGlzdC50b2dnbGUoJ2FjdGl2ZScsIGlzT3BlbilcblxuICAgICAgaWYgKGlzT3Blbikge1xuICAgICAgICB1cGRhdGVDb250ZXh0KClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBidXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0b2dnbGUpXG5cbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgKGUpID0+IHtcbiAgICAgIGlmIChtYXRjaEhvdGtleShlLCBtYWluSG90a2V5KSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KClcbiAgICAgICAgdG9nZ2xlKClcbiAgICAgIH1cbiAgICB9KVxuXG4gICAgaWYgKG9wZW4gJiYgc2VydmljZXNTdGFydGVkKSB7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgdG9nZ2xlKClcbiAgICAgIH0sIEFVVE9fT1BFTl9ERUxBWSlcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDmmL7npLrpgJrnn6VcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIOmAmuefpea2iOaBr1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNob3dOb3RpZmljYXRpb24obWVzc2FnZSkge1xuICAgICAgY29uc3Qgbm90aWZpY2F0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JylcbiAgICAgIG5vdGlmaWNhdGlvbi5jbGFzc05hbWUgPSAnb3BlbmNvZGUtbm90aWZpY2F0aW9uJ1xuICAgICAgbm90aWZpY2F0aW9uLnRleHRDb250ZW50ID0gbWVzc2FnZVxuICAgICAgY2hhdC5hcHBlbmRDaGlsZChub3RpZmljYXRpb24pXG5cbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBub3RpZmljYXRpb24ucmVtb3ZlKClcbiAgICAgIH0sIE5PVElGSUNBVElPTl9EVVJBVElPTilcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDmt7vliqDpgInkuK3lhYPntKBcbiAgICAgKiBAcGFyYW0ge1NlbGVjdGVkRWxlbWVudH0gZWxlbWVudEluZm8gLSDlhYPntKDkv6Hmga9cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhZGRFbGVtZW50KGVsZW1lbnRJbmZvKSB7XG4gICAgICBjb25zdCBrZXkgPSBlbGVtZW50SW5mby5maWxlUGF0aCAmJiBlbGVtZW50SW5mby5saW5lXG4gICAgICAgID8gYCR7ZWxlbWVudEluZm8uZmlsZVBhdGh9OiR7ZWxlbWVudEluZm8ubGluZX1gXG4gICAgICAgIDogbnVsbFxuXG4gICAgICBjb25zdCBleGlzdHMgPSBrZXkgJiYgc2VsZWN0ZWRFbGVtZW50cy5zb21lKGVsID0+IHtcbiAgICAgICAgY29uc3QgZWxLZXkgPSBlbC5maWxlUGF0aCAmJiBlbC5saW5lID8gYCR7ZWwuZmlsZVBhdGh9OiR7ZWwubGluZX1gIDogbnVsbFxuICAgICAgICByZXR1cm4gZWxLZXkgPT09IGtleVxuICAgICAgfSlcblxuICAgICAgaWYgKCFleGlzdHMpIHtcbiAgICAgICAgc2VsZWN0ZWRFbGVtZW50cy5wdXNoKGVsZW1lbnRJbmZvKVxuICAgICAgICBzYXZlU2VsZWN0ZWRFbGVtZW50cyhzZWxlY3RlZEVsZW1lbnRzKVxuICAgICAgICByZW5kZXJTZWxlY3RlZE5vZGVzKClcbiAgICAgICAgaWYgKGlzU2VsZWN0TW9kZSkge1xuICAgICAgICAgIHJlbmRlclNlbGVjdGVkQnViYmxlcygpXG4gICAgICAgIH1cbiAgICAgICAgc2hvd05vdGlmaWNhdGlvbihg5bey6YCJ5Lit5YWD57SgICgke3NlbGVjdGVkRWxlbWVudHMubGVuZ3RofeS4qilgKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2hvd05vdGlmaWNhdGlvbign6K+l5YWD57Sg5bey6YCJ5LitJylcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDnp7vpmaTpgInkuK3lhYPntKBcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gaW5kZXggLSDlhYPntKDntKLlvJVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZW1vdmVFbGVtZW50KGluZGV4KSB7XG4gICAgICBzZWxlY3RlZEVsZW1lbnRzLnNwbGljZShpbmRleCwgMSlcbiAgICAgIHNhdmVTZWxlY3RlZEVsZW1lbnRzKHNlbGVjdGVkRWxlbWVudHMpXG4gICAgICByZW5kZXJTZWxlY3RlZE5vZGVzKClcbiAgICAgIHVwZGF0ZVRvb2xiYXJTdGF0ZSgpXG4gICAgICBzZW5kU2VsZWN0ZWRFbGVtZW50cygpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog5riF6Zmk5omA5pyJ6YCJ5Lit5YWD57SgXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xlYXJBbGxFbGVtZW50cygpIHtcbiAgICAgIHNlbGVjdGVkRWxlbWVudHMgPSBbXVxuICAgICAgc2F2ZVNlbGVjdGVkRWxlbWVudHMoc2VsZWN0ZWRFbGVtZW50cylcbiAgICAgIHJlbmRlclNlbGVjdGVkTm9kZXMoKVxuICAgICAgdXBkYXRlVG9vbGJhclN0YXRlKClcbiAgICAgIHNlbmRTZWxlY3RlZEVsZW1lbnRzKClcbiAgICAgIHNob3dOb3RpZmljYXRpb24oJ+W3sua4hemZpOaJgOaciemAieS4reWFg+e0oCcpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog5pu05paw5bel5YW35qCP54q25oCBXG4gICAgICovXG4gICAgZnVuY3Rpb24gdXBkYXRlVG9vbGJhclN0YXRlKCkge1xuICAgICAgaWYgKHNlbGVjdGVkRWxlbWVudHMubGVuZ3RoID4gMCkge1xuICAgICAgICByaWdodFRvb2xiYXIuY2xhc3NMaXN0LnJlbW92ZSgnY29sbGFwc2VkJylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJpZ2h0VG9vbGJhci5jbGFzc0xpc3QuYWRkKCdjb2xsYXBzZWQnKVxuICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBAdHlwZSB7Ym9vbGVhbn0g5piv5ZCm5aSE5LqO5YWD57Sg6YCJ5oup5qih5byPICovXG4gICAgbGV0IGlzU2VsZWN0TW9kZSA9IGZhbHNlXG5cbiAgICAvKipcbiAgICAgKiDliIfmjaLlhYPntKDpgInmi6nmqKHlvI9cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b2dnbGVTZWxlY3RNb2RlKCkge1xuICAgICAgY29uc3QgaW5zcGVjdG9yID0gd2luZG93Ll9fVlVFX0lOU1BFQ1RPUl9fXG4gICAgICBcbiAgICAgIGlmICghaW5zcGVjdG9yKSB7XG4gICAgICAgIHNob3dOb3RpZmljYXRpb24oJ1Z1ZSBJbnNwZWN0b3Ig5pyq5Yqg6L2977yM5peg5rOV5L2/55So5YWD57Sg6YCJ5oup5Yqf6IO9JylcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgICBcbiAgICAgIGlzU2VsZWN0TW9kZSA9ICFpc1NlbGVjdE1vZGVcbiAgICAgIHNlbGVjdEJ1dHRvbi5jbGFzc0xpc3QudG9nZ2xlKCdhY3RpdmUnLCBpc1NlbGVjdE1vZGUpXG4gICAgICBzZWxlY3RNb2RlSGludC5jbGFzc0xpc3QudG9nZ2xlKCd2aXNpYmxlJywgaXNTZWxlY3RNb2RlKVxuICAgICAgc2VsZWN0ZWRCdWJibGVzLmNsYXNzTGlzdC50b2dnbGUoJ3Zpc2libGUnLCBpc1NlbGVjdE1vZGUpXG4gICAgICBcbiAgICAgIGlmIChpc1NlbGVjdE1vZGUpIHtcbiAgICAgICAgY2hhdC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnXG4gICAgICAgIGluc3BlY3Rvci5lbmFibGUoKVxuICAgICAgICByZW5kZXJTZWxlY3RlZEJ1YmJsZXMoKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2hhdC5zdHlsZS5kaXNwbGF5ID0gJydcbiAgICAgICAgaW5zcGVjdG9yLmRpc2FibGUoKVxuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIOmAgOWHuumAieaLqeaooeW8j1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGV4aXRTZWxlY3RNb2RlKCkge1xuICAgICAgaWYgKCFpc1NlbGVjdE1vZGUpIHJldHVyblxuICAgICAgXG4gICAgICBjb25zdCBpbnNwZWN0b3IgPSB3aW5kb3cuX19WVUVfSU5TUEVDVE9SX19cbiAgICAgIGlmIChpbnNwZWN0b3IpIHtcbiAgICAgICAgaW5zcGVjdG9yLmRpc2FibGUoKVxuICAgICAgfVxuICAgICAgXG4gICAgICBpc1NlbGVjdE1vZGUgPSBmYWxzZVxuICAgICAgc2VsZWN0QnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoJ2FjdGl2ZScpXG4gICAgICBzZWxlY3RNb2RlSGludC5jbGFzc0xpc3QucmVtb3ZlKCd2aXNpYmxlJylcbiAgICAgIHNlbGVjdGVkQnViYmxlcy5jbGFzc0xpc3QucmVtb3ZlKCd2aXNpYmxlJylcbiAgICAgIGNoYXQuc3R5bGUuZGlzcGxheSA9ICcnXG4gICAgfVxuXG4gICAgLy8gRVNDIOmUrumAgOWHuumAieaLqeaooeW8j1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCAoZSkgPT4ge1xuICAgICAgaWYgKGUua2V5ID09PSAnRXNjYXBlJyAmJiBpc1NlbGVjdE1vZGUpIHtcbiAgICAgICAgZXhpdFNlbGVjdE1vZGUoKVxuICAgICAgfVxuICAgIH0pXG5cbiAgICAvKipcbiAgICAgKiDmuLLmn5Plt7LpgInoioLngrnmsJTms6FcbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZW5kZXJTZWxlY3RlZEJ1YmJsZXMoKSB7XG4gICAgICBzZWxlY3RlZEJ1YmJsZXMuaW5uZXJIVE1MID0gJydcbiAgICAgIFxuICAgICAgaWYgKHNlbGVjdGVkRWxlbWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHNlbGVjdGVkQnViYmxlcy5pbm5lckhUTUwgPSAnPGRpdiBjbGFzcz1cIm9wZW5jb2RlLWJ1YmJsZS1lbXB0eVwiPuaaguaXoOmAieS4reWFg+e0oDwvZGl2PidcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgICBcbiAgICAgIHNlbGVjdGVkRWxlbWVudHMuZm9yRWFjaCgoZWxlbWVudCwgaW5kZXgpID0+IHtcbiAgICAgICAgY29uc3QgYnViYmxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JylcbiAgICAgICAgYnViYmxlLmNsYXNzTmFtZSA9ICdvcGVuY29kZS1zZWxlY3RlZC1idWJibGUnXG4gICAgICAgIFxuICAgICAgICBjb25zdCBkZXNjcmlwdGlvbiA9IGVsZW1lbnQuZGVzY3JpcHRpb24gfHwgJ+acquefpeWFg+e0oCdcbiAgICAgICAgY29uc3QgZmlsZU5hbWUgPSBlbGVtZW50LmZpbGVQYXRoID8gZWxlbWVudC5maWxlUGF0aC5zcGxpdCgnLycpLnBvcCgpIDogJydcbiAgICAgICAgY29uc3QgbGluZUluZm8gPSBlbGVtZW50LmxpbmUgPyBgOiR7ZWxlbWVudC5saW5lfWAgOiAnJ1xuICAgICAgICBcbiAgICAgICAgYnViYmxlLmlubmVySFRNTCA9IGBcbiAgICAgICAgICA8c3BhbiBjbGFzcz1cIm9wZW5jb2RlLWJ1YmJsZS10ZXh0XCI+JHtkZXNjcmlwdGlvbn08L3NwYW4+XG4gICAgICAgICAgJHtmaWxlTmFtZSA/IGA8c3BhbiBjbGFzcz1cIm9wZW5jb2RlLWJ1YmJsZS1maWxlXCI+JHtmaWxlTmFtZX0ke2xpbmVJbmZvfTwvc3Bhbj5gIDogJyd9XG4gICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cIm9wZW5jb2RlLWJ1YmJsZS1yZW1vdmVcIiBkYXRhLWluZGV4PVwiJHtpbmRleH1cIj7DlzwvYnV0dG9uPlxuICAgICAgICBgXG4gICAgICAgIFxuICAgICAgICBidWJibGUucXVlcnlTZWxlY3RvcignLm9wZW5jb2RlLWJ1YmJsZS1yZW1vdmUnKS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIChlKSA9PiB7XG4gICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKVxuICAgICAgICAgIHJlbW92ZUVsZW1lbnQoaW5kZXgpXG4gICAgICAgICAgcmVuZGVyU2VsZWN0ZWRCdWJibGVzKClcbiAgICAgICAgfSlcbiAgICAgICAgXG4gICAgICAgIHNlbGVjdGVkQnViYmxlcy5hcHBlbmRDaGlsZChidWJibGUpXG4gICAgICB9KVxuICAgIH1cbiAgICBmdW5jdGlvbiByZW5kZXJTZWxlY3RlZE5vZGVzKCkge1xuICAgICAgc2VsZWN0ZWROb2Rlc0NvbnRhaW5lci5pbm5lckhUTUwgPSAnJ1xuICAgICAgXG4gICAgICBpZiAoc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmlnaHRUb29sYmFyLmNsYXNzTGlzdC5hZGQoJ2NvbGxhcHNlZCcpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByaWdodFRvb2xiYXIuY2xhc3NMaXN0LnJlbW92ZSgnY29sbGFwc2VkJylcbiAgICAgIH1cbiAgICAgIFxuICAgICAgc2VsZWN0ZWRFbGVtZW50cy5mb3JFYWNoKChlbGVtZW50LCBpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCBub2RlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JylcbiAgICAgICAgbm9kZS5jbGFzc05hbWUgPSAnb3BlbmNvZGUtc2VsZWN0ZWQtbm9kZSdcbiAgICAgICAgXG4gICAgICAgIGNvbnN0IGRlc2NyaXB0aW9uID0gZWxlbWVudC5kZXNjcmlwdGlvbiB8fCAn5pyq55+l5YWD57SgJ1xuICAgICAgICBjb25zdCB0ZXh0UHJldmlldyA9IGVsZW1lbnQuaW5uZXJUZXh0ID8gZWxlbWVudC5pbm5lclRleHQuc3Vic3RyaW5nKDAsIDMwKSA6ICcnXG4gICAgICAgIGNvbnN0IGZpbGVOYW1lID0gZWxlbWVudC5maWxlUGF0aCA/IGVsZW1lbnQuZmlsZVBhdGguc3BsaXQoJy8nKS5wb3AoKSA6ICfmnKrnn6Xmlofku7YnXG4gICAgICAgIGNvbnN0IGxpbmVJbmZvID0gZWxlbWVudC5saW5lID8gYDoke2VsZW1lbnQubGluZX1gIDogJydcbiAgICAgICAgXG4gICAgICAgIG5vZGUuaW5uZXJIVE1MID0gYFxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJvcGVuY29kZS1ub2RlLWNvbnRlbnRcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwib3BlbmNvZGUtbm9kZS10ZXh0XCI+JHtkZXNjcmlwdGlvbn08L3NwYW4+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm9wZW5jb2RlLW5vZGUtZmlsZVwiPiR7dGV4dFByZXZpZXcgPyB0ZXh0UHJldmlldyArICcgwrcgJyA6ICcnfSR7ZmlsZU5hbWV9JHtsaW5lSW5mb308L3NwYW4+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cIm9wZW5jb2RlLW5vZGUtcmVtb3ZlXCIgZGF0YS1pbmRleD1cIiR7aW5kZXh9XCI+w5c8L2J1dHRvbj5cbiAgICAgICAgYFxuICAgICAgICBcbiAgICAgICAgbm9kZS5xdWVyeVNlbGVjdG9yKCcub3BlbmNvZGUtbm9kZS1yZW1vdmUnKS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIChlKSA9PiB7XG4gICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKVxuICAgICAgICAgIHJlbW92ZUVsZW1lbnQoaW5kZXgpXG4gICAgICAgIH0pXG4gICAgICAgIFxuICAgICAgICBzZWxlY3RlZE5vZGVzQ29udGFpbmVyLmFwcGVuZENoaWxkKG5vZGUpXG4gICAgICB9KVxuICAgIH1cblxuICAgIC8vIOe7keWumumAieaLqeaMiemSrueCueWHu+S6i+S7tlxuICAgIHNlbGVjdEJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRvZ2dsZVNlbGVjdE1vZGUpXG5cbiAgICAvKipcbiAgICAgKiDlj5HpgIHpgInkuK3lhYPntKDliLDmnI3liqHlmahcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzZW5kU2VsZWN0ZWRFbGVtZW50cygpIHtcbiAgICAgIGlmICghc2VydmljZXNTdGFydGVkKSByZXR1cm5cblxuICAgICAgZmV0Y2goJy9fX29wZW5jb2RlX2NvbnRleHRfXycsIHtcbiAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9LFxuICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgdXJsOiBjdXJyZW50UGFnZVVybCxcbiAgICAgICAgICB0aXRsZTogY3VycmVudFBhZ2VUaXRsZSxcbiAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRzOiBzZWxlY3RlZEVsZW1lbnRzXG4gICAgICAgIH0pXG4gICAgICB9KS5jYXRjaCgoKSA9PiB7fSlcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDkuI7mnI3liqHlmajlkIzmraXpgInkuK3lhYPntKBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzeW5jV2l0aFNlcnZlcigpIHtcbiAgICAgIGlmICghc2VydmljZXNTdGFydGVkKSByZXR1cm5cblxuICAgICAgZmV0Y2goJy9fX29wZW5jb2RlX2NvbnRleHRfXycpXG4gICAgICAgIC50aGVuKHJlcyA9PiByZXMuanNvbigpKVxuICAgICAgICAudGhlbihkYXRhID0+IHtcbiAgICAgICAgICBpZiAoZGF0YS5zZWxlY3RlZEVsZW1lbnRzICYmIGRhdGEuc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggPT09IDAgJiYgc2VsZWN0ZWRFbGVtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBzZWxlY3RlZEVsZW1lbnRzID0gW11cbiAgICAgICAgICAgIHNhdmVTZWxlY3RlZEVsZW1lbnRzKHNlbGVjdGVkRWxlbWVudHMpXG4gICAgICAgICAgICByZW5kZXJTZWxlY3RlZE5vZGVzKClcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaCgoKSA9PiB7fSlcbiAgICB9XG5cbiAgICBzZXRJbnRlcnZhbChzeW5jV2l0aFNlcnZlciwgU0VSVkVSX1NZTkNfSU5URVJWQUwpXG5cbiAgICAvKipcbiAgICAgKiDmiKrmlq3lrZfnrKbkuLJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyIC0g5Y6f5a2X56ym5LiyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1heExlbmd0aCAtIOacgOWkp+mVv+W6plxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IOaIquaWreWQjueahOWtl+espuS4slxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRydW5jYXRlKHN0ciwgbWF4TGVuZ3RoKSB7XG4gICAgICBpZiAoIXN0cikgcmV0dXJuICcnXG4gICAgICByZXR1cm4gc3RyLmxlbmd0aCA+IG1heExlbmd0aCA/IHN0ci5zdWJzdHJpbmcoMCwgbWF4TGVuZ3RoKSArICcuLi4nIDogc3RyXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog6I635Y+W5YWD57Sg55qE55u05o6l5paH5pys5YaF5a65XG4gICAgICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50IC0gRE9NIOWFg+e0oFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IOebtOaOpeaWh+acrOWGheWuuVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldERpcmVjdFRleHQoZWxlbWVudCkge1xuICAgICAgbGV0IHRleHQgPSAnJ1xuICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiBlbGVtZW50LmNoaWxkTm9kZXMpIHtcbiAgICAgICAgaWYgKGNoaWxkLm5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSkge1xuICAgICAgICAgIHRleHQgKz0gY2hpbGQudGV4dENvbnRlbnQgfHwgJydcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRleHQudHJpbSgpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog6I635Y+W5YWD57Sg5o+P6L+w5L+h5oGvXG4gICAgICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50IC0gRE9NIOWFg+e0oFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IOWFg+e0oOaPj+i/sFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldEVsZW1lbnREZXNjcmlwdGlvbihlbGVtZW50KSB7XG4gICAgICBjb25zdCB0YWcgPSBlbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKVxuICAgICAgY29uc3QgcGFydHMgPSBbdGFnXVxuICAgICAgXG4gICAgICBjb25zdCBpZCA9IGVsZW1lbnQuaWRcbiAgICAgIGlmIChpZCkgcGFydHMucHVzaChgIyR7aWR9YClcbiAgICAgIFxuICAgICAgY29uc3QgY2xhc3NOYW1lID0gZWxlbWVudC5jbGFzc05hbWUgJiYgdHlwZW9mIGVsZW1lbnQuY2xhc3NOYW1lID09PSAnc3RyaW5nJ1xuICAgICAgICA/IGVsZW1lbnQuY2xhc3NOYW1lLnRyaW0oKS5zcGxpdCgvXFxzKy8pLmZpbHRlcihCb29sZWFuKS5zbGljZSgwLCAyKS5qb2luKCcuJylcbiAgICAgICAgOiAnJ1xuICAgICAgaWYgKGNsYXNzTmFtZSkgcGFydHMucHVzaChgLiR7Y2xhc3NOYW1lfWApXG4gICAgICBcbiAgICAgIGNvbnN0IG5hbWUgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnbmFtZScpXG4gICAgICBpZiAobmFtZSkgcGFydHMucHVzaChgW25hbWU9XCIke25hbWV9XCJdYClcbiAgICAgIFxuICAgICAgY29uc3QgcGxhY2Vob2xkZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgncGxhY2Vob2xkZXInKVxuICAgICAgaWYgKHBsYWNlaG9sZGVyKSBwYXJ0cy5wdXNoKGBbcGxhY2Vob2xkZXI9XCIke3BsYWNlaG9sZGVyLnN1YnN0cmluZygwLCAyMCl9XCJdYClcbiAgICAgIFxuICAgICAgY29uc3Qgc3JjID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3NyYycpXG4gICAgICBpZiAoc3JjKSBwYXJ0cy5wdXNoKGBbc3JjXWApXG4gICAgICBcbiAgICAgIGNvbnN0IGhyZWYgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnaHJlZicpXG4gICAgICBpZiAoaHJlZiAmJiBocmVmICE9PSAnIycpIHBhcnRzLnB1c2goYFtocmVmXWApXG4gICAgICBcbiAgICAgIHJldHVybiBwYXJ0cy5qb2luKCcnKVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIOiuvue9riBWdWUgSW5zcGVjdG9yIOmSqeWtkFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNldHVwSW5zcGVjdG9ySG9vaygpIHtcbiAgICAgIGlmICh3aW5kb3cuX19WVUVfSU5TUEVDVE9SX18pIHtcbiAgICAgICAgY29uc3QgaW5zcGVjdG9yID0gd2luZG93Ll9fVlVFX0lOU1BFQ1RPUl9fXG4gICAgICAgIGNvbnN0IG9yaWdpbmFsSGFuZGxlQ2xpY2sgPSBpbnNwZWN0b3IuaGFuZGxlQ2xpY2suYmluZChpbnNwZWN0b3IpXG5cbiAgICAgICAgaW5zcGVjdG9yLmhhbmRsZUNsaWNrID0gZnVuY3Rpb24oZSkge1xuICAgICAgICAgIGlmIChpc1NlbGVjdE1vZGUpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgdGFyZ2V0Tm9kZSwgcGFyYW1zIH0gPSBpbnNwZWN0b3IuZ2V0VGFyZ2V0Tm9kZShlKVxuICAgICAgICAgICAgaWYgKHRhcmdldE5vZGUgJiYgcGFyYW1zKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGlubmVyVGV4dCA9IGdldERpcmVjdFRleHQodGFyZ2V0Tm9kZSlcbiAgICAgICAgICAgICAgY29uc3QgZGVzY3JpcHRpb24gPSBnZXRFbGVtZW50RGVzY3JpcHRpb24odGFyZ2V0Tm9kZSlcblxuICAgICAgICAgICAgICBjb25zdCBlbGVtZW50SW5mbyA9IHtcbiAgICAgICAgICAgICAgICBmaWxlUGF0aDogcGFyYW1zLmZpbGUsXG4gICAgICAgICAgICAgICAgbGluZTogcGFyYW1zLmxpbmUsXG4gICAgICAgICAgICAgICAgY29sdW1uOiBwYXJhbXMuY29sdW1uLFxuICAgICAgICAgICAgICAgIGlubmVyVGV4dDogdHJ1bmNhdGUoaW5uZXJUZXh0LCAyMDApLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgYWRkRWxlbWVudChlbGVtZW50SW5mbylcbiAgICAgICAgICAgICAgc2VuZFNlbGVjdGVkRWxlbWVudHMoKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIG9yaWdpbmFsSGFuZGxlQ2xpY2suY2FsbChpbnNwZWN0b3IsIGUpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAod2luZG93Ll9fVlVFX0lOU1BFQ1RPUl9fKSB7XG4gICAgICBzZXR1cEluc3BlY3Rvckhvb2soKVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBjaGVja0luc3BlY3RvciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgaWYgKHdpbmRvdy5fX1ZVRV9JTlNQRUNUT1JfXykge1xuICAgICAgICAgIHNldHVwSW5zcGVjdG9ySG9vaygpXG4gICAgICAgICAgY2xlYXJJbnRlcnZhbChjaGVja0luc3BlY3RvcilcbiAgICAgICAgfVxuICAgICAgfSwgSU5TUEVDVE9SX0NIRUNLX0lOVEVSVkFMKVxuICAgIH1cblxuICAgIC8vIOWvvOWHuuWFqOWxgCBBUElcbiAgICB3aW5kb3cuT3BlbkNvZGVXaWRnZXQgPSB7XG4gICAgICBvcGVuOiAoKSA9PiB7IGlmICghaXNPcGVuKSB0b2dnbGUoKSB9LFxuICAgICAgY2xvc2U6ICgpID0+IHsgaWYgKGlzT3BlbikgdG9nZ2xlKCkgfSxcbiAgICAgIHRvZ2dsZSxcbiAgICAgIHNob3dOb3RpZmljYXRpb24sXG4gICAgICB1cGRhdGVDb250ZXh0LFxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiDmnoTlu7rmjILku7bmoLflvI9cbiAgICogQHJldHVybnMge3N0cmluZ30gQ1NTIOagt+W8j+Wtl+espuS4slxuICAgKi9cbiAgZnVuY3Rpb24gYnVpbGRXaWRnZXRTdHlsZXMoKSB7XG4gICAgcmV0dXJuIGBcbiAgICAgIC5vcGVuY29kZS13aWRnZXQge1xuICAgICAgICBwb3NpdGlvbjogZml4ZWQ7XG4gICAgICAgIHotaW5kZXg6IDk5OTk5OTtcbiAgICAgICAgZm9udC1mYW1pbHk6IC1hcHBsZS1zeXN0ZW0sIEJsaW5rTWFjU3lzdGVtRm9udCwgJ1NlZ29lIFVJJywgUm9ib3RvLCBzYW5zLXNlcmlmO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtd2lkZ2V0LmJvdHRvbS1yaWdodCB7XG4gICAgICAgIGJvdHRvbTogMjBweDtcbiAgICAgICAgcmlnaHQ6IDIwcHg7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS13aWRnZXQuYm90dG9tLWxlZnQge1xuICAgICAgICBib3R0b206IDIwcHg7XG4gICAgICAgIGxlZnQ6IDIwcHg7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS13aWRnZXQudG9wLXJpZ2h0IHtcbiAgICAgICAgdG9wOiAyMHB4O1xuICAgICAgICByaWdodDogMjBweDtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLXdpZGdldC50b3AtbGVmdCB7XG4gICAgICAgIHRvcDogMjBweDtcbiAgICAgICAgbGVmdDogMjBweDtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWJ1dHRvbiB7XG4gICAgICAgIHdpZHRoOiA2MHB4O1xuICAgICAgICBoZWlnaHQ6IDYwcHg7XG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcbiAgICAgICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgIzY2N2VlYSAwJSwgIzc2NGJhMiAxMDAlKTtcbiAgICAgICAgYm9yZGVyOiBub25lO1xuICAgICAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgICAgIGJveC1zaGFkb3c6IDAgNHB4IDE1cHggcmdiYSgxMDIsIDEyNiwgMjM0LCAwLjQpO1xuICAgICAgICB0cmFuc2l0aW9uOiBhbGwgMC4zcyBlYXNlO1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgICAgICAgY29sb3I6IHdoaXRlO1xuICAgICAgICBwYWRkaW5nOiAwO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtYnV0dG9uOmhvdmVyIHtcbiAgICAgICAgdHJhbnNmb3JtOiBzY2FsZSgxLjEpO1xuICAgICAgICBib3gtc2hhZG93OiAwIDZweCAyMHB4IHJnYmEoMTAyLCAxMjYsIDIzNCwgMC42KTtcbiAgICAgICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZywgIzc2NGJhMiAwJSwgIzY2N2VlYSAxMDAlKTtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWJ1dHRvbi5hY3RpdmUge1xuICAgICAgICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCAjZjA5M2ZiIDAlLCAjZjU1NzZjIDEwMCUpO1xuICAgICAgICBib3gtc2hhZG93OiAwIDZweCAyMHB4IHJnYmEoMjQwLCAxNDcsIDI1MSwgMC40KTtcbiAgICAgICAgdHJhbnNmb3JtOiByb3RhdGUoMTgwZGVnKTtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWJ1dHRvbi5sb2FkaW5nIHtcbiAgICAgICAgYW5pbWF0aW9uOiBwdWxzZSAxcyBpbmZpbml0ZTtcbiAgICAgIH1cblxuICAgICAgQGtleWZyYW1lcyBwdWxzZSB7XG4gICAgICAgIDAlLCAxMDAlIHsgb3BhY2l0eTogMTsgfVxuICAgICAgICA1MCUgeyBvcGFjaXR5OiAwLjU7IH1cbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWNoYXQge1xuICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICAgIHdpZHRoOiA3MDBweDtcbiAgICAgICAgaGVpZ2h0OiA4MHZoO1xuICAgICAgICBiYWNrZ3JvdW5kOiB3aGl0ZTtcbiAgICAgICAgYm9yZGVyLXJhZGl1czogMTZweDtcbiAgICAgICAgYm94LXNoYWRvdzogMCA4cHggMzJweCByZ2JhKDAsIDAsIDAsIDAuMTIpO1xuICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgICAgICBvcGFjaXR5OiAwO1xuICAgICAgICB2aXNpYmlsaXR5OiBoaWRkZW47XG4gICAgICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgyMHB4KSBzY2FsZSgwLjk1KTtcbiAgICAgICAgdHJhbnNpdGlvbjogYWxsIDAuM3MgZWFzZTtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLXdpZGdldC5ib3R0b20tcmlnaHQgLm9wZW5jb2RlLWNoYXQge1xuICAgICAgICBib3R0b206IDgwcHg7XG4gICAgICAgIHJpZ2h0OiAwO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtd2lkZ2V0LmJvdHRvbS1sZWZ0IC5vcGVuY29kZS1jaGF0IHtcbiAgICAgICAgYm90dG9tOiA4MHB4O1xuICAgICAgICBsZWZ0OiAwO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtd2lkZ2V0LnRvcC1yaWdodCAub3BlbmNvZGUtY2hhdCB7XG4gICAgICAgIHRvcDogODBweDtcbiAgICAgICAgcmlnaHQ6IDA7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS13aWRnZXQudG9wLWxlZnQgLm9wZW5jb2RlLWNoYXQge1xuICAgICAgICB0b3A6IDgwcHg7XG4gICAgICAgIGxlZnQ6IDA7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1jaGF0Lm9wZW4ge1xuICAgICAgICBvcGFjaXR5OiAxO1xuICAgICAgICB2aXNpYmlsaXR5OiB2aXNpYmxlO1xuICAgICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMCkgc2NhbGUoMSk7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1zZXNzaW9uLWxpc3Qge1xuICAgICAgICB3aWR0aDogMjQwcHg7XG4gICAgICAgIGJhY2tncm91bmQ6ICNmOGY5ZmE7XG4gICAgICAgIGJvcmRlci1yaWdodDogMXB4IHNvbGlkICNlNWU3ZWI7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgICAgIGZsZXgtc2hyaW5rOiAwO1xuICAgICAgICB0cmFuc2l0aW9uOiB3aWR0aCAwLjJzIGVhc2U7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1zZXNzaW9uLWxpc3QuY29sbGFwc2VkIHtcbiAgICAgICAgd2lkdGg6IDQwcHg7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1zZXNzaW9uLXRvZ2dsZSB7XG4gICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgICBoZWlnaHQ6IDQwcHg7XG4gICAgICAgIGJvcmRlcjogbm9uZTtcbiAgICAgICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XG4gICAgICAgIGNvbG9yOiAjNmI3MjgwO1xuICAgICAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICAgICAgICB0cmFuc2l0aW9uOiBhbGwgMC4ycztcbiAgICAgICAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICNlNWU3ZWI7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1zZXNzaW9uLXRvZ2dsZTpob3ZlciB7XG4gICAgICAgIGJhY2tncm91bmQ6ICNlNWU3ZWI7XG4gICAgICAgIGNvbG9yOiAjMzc0MTUxO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtc2Vzc2lvbi1saXN0LmNvbGxhcHNlZCAub3BlbmNvZGUtc2Vzc2lvbi1saXN0LWhlYWRlcixcbiAgICAgIC5vcGVuY29kZS1zZXNzaW9uLWxpc3QuY29sbGFwc2VkIC5vcGVuY29kZS1zZXNzaW9uLWxpc3QtY29udGVudCB7XG4gICAgICAgIGRpc3BsYXk6IG5vbmU7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1zZXNzaW9uLWxpc3QtaGVhZGVyIHtcbiAgICAgICAgcGFkZGluZzogMTZweDtcbiAgICAgICAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICNlNWU3ZWI7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcbiAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgICAgZm9udC13ZWlnaHQ6IDYwMDtcbiAgICAgICAgZm9udC1zaXplOiAxNHB4O1xuICAgICAgICBjb2xvcjogIzM3NDE1MTtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLW5ldy1zZXNzaW9uLWJ0biB7XG4gICAgICAgIHdpZHRoOiAyOHB4O1xuICAgICAgICBoZWlnaHQ6IDI4cHg7XG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDZweDtcbiAgICAgICAgYm9yZGVyOiBub25lO1xuICAgICAgICBiYWNrZ3JvdW5kOiAjM2I4MmY2O1xuICAgICAgICBjb2xvcjogd2hpdGU7XG4gICAgICAgIGZvbnQtc2l6ZTogMThweDtcbiAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgICAgICAgdHJhbnNpdGlvbjogYWxsIDAuMnM7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1uZXctc2Vzc2lvbi1idG46aG92ZXIge1xuICAgICAgICBiYWNrZ3JvdW5kOiAjMjU2M2ViO1xuICAgICAgICB0cmFuc2Zvcm06IHNjYWxlKDEuMDUpO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtc2Vzc2lvbi1saXN0LWNvbnRlbnQge1xuICAgICAgICBmbGV4OiAxO1xuICAgICAgICBvdmVyZmxvdy15OiBhdXRvO1xuICAgICAgICBwYWRkaW5nOiA4cHg7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1zZXNzaW9uLWl0ZW0ge1xuICAgICAgICBwYWRkaW5nOiAxMnB4O1xuICAgICAgICBib3JkZXItcmFkaXVzOiA4cHg7XG4gICAgICAgIGN1cnNvcjogcG9pbnRlcjtcbiAgICAgICAgdHJhbnNpdGlvbjogYWxsIDAuMnM7XG4gICAgICAgIG1hcmdpbi1ib3R0b206IDRweDtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLXNlc3Npb24taXRlbTpob3ZlciB7XG4gICAgICAgIGJhY2tncm91bmQ6ICNlNWU3ZWI7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1zZXNzaW9uLWl0ZW0uYWN0aXZlIHtcbiAgICAgICAgYmFja2dyb3VuZDogIzNiODJmNjtcbiAgICAgICAgY29sb3I6IHdoaXRlO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtc2Vzc2lvbi10aXRsZSB7XG4gICAgICAgIGZvbnQtc2l6ZTogMTRweDtcbiAgICAgICAgZm9udC13ZWlnaHQ6IDUwMDtcbiAgICAgICAgbWFyZ2luLWJvdHRvbTogNHB4O1xuICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgICAgICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcbiAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLXNlc3Npb24tbWV0YSB7XG4gICAgICAgIGZvbnQtc2l6ZTogMTJweDtcbiAgICAgICAgb3BhY2l0eTogMC42O1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtc2Vzc2lvbi1oZWFkZXIge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICAgIG1hcmdpbi1ib3R0b206IDRweDtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLXNlc3Npb24tZGVsZXRlLWJ0biB7XG4gICAgICAgIHdpZHRoOiAyMHB4O1xuICAgICAgICBoZWlnaHQ6IDIwcHg7XG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDRweDtcbiAgICAgICAgYm9yZGVyOiBub25lO1xuICAgICAgICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcbiAgICAgICAgY29sb3I6ICM2YjcyODA7XG4gICAgICAgIGZvbnQtc2l6ZTogMTZweDtcbiAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgICAgICAgdHJhbnNpdGlvbjogYWxsIDAuMnM7XG4gICAgICAgIG9wYWNpdHk6IDA7XG4gICAgICAgIGZsZXgtc2hyaW5rOiAwO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtc2Vzc2lvbi1pdGVtOmhvdmVyIC5vcGVuY29kZS1zZXNzaW9uLWRlbGV0ZS1idG4ge1xuICAgICAgICBvcGFjaXR5OiAxO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtc2Vzc2lvbi1kZWxldGUtYnRuOmhvdmVyIHtcbiAgICAgICAgYmFja2dyb3VuZDogI2VmNDQ0NDtcbiAgICAgICAgY29sb3I6IHdoaXRlO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtc2Vzc2lvbi1pdGVtLmFjdGl2ZSAub3BlbmNvZGUtc2Vzc2lvbi1kZWxldGUtYnRuIHtcbiAgICAgICAgY29sb3I6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC43KTtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLXNlc3Npb24taXRlbS5hY3RpdmUgLm9wZW5jb2RlLXNlc3Npb24tZGVsZXRlLWJ0bjpob3ZlciB7XG4gICAgICAgIGJhY2tncm91bmQ6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4yKTtcbiAgICAgICAgY29sb3I6IHdoaXRlO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtaWZyYW1lLWNvbnRhaW5lciB7XG4gICAgICAgIGZsZXg6IDE7XG4gICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWxvYWRpbmctb3ZlcmxheSB7XG4gICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgICAgdG9wOiAwO1xuICAgICAgICBsZWZ0OiAwO1xuICAgICAgICByaWdodDogMDtcbiAgICAgICAgYm90dG9tOiAwO1xuICAgICAgICBiYWNrZ3JvdW5kOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuOSk7XG4gICAgICAgIGRpc3BsYXk6IG5vbmU7XG4gICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICAgICAgICB6LWluZGV4OiAxMDtcbiAgICAgICAgdHJhbnNpdGlvbjogb3BhY2l0eSAwLjNzIGVhc2U7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1sb2FkaW5nLW92ZXJsYXkudmlzaWJsZSB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1sb2FkaW5nLXNwaW5uZXIge1xuICAgICAgICB3aWR0aDogNDBweDtcbiAgICAgICAgaGVpZ2h0OiA0MHB4O1xuICAgICAgICBib3JkZXI6IDNweCBzb2xpZCAjZTVlN2ViO1xuICAgICAgICBib3JkZXItdG9wLWNvbG9yOiAjM2I4MmY2O1xuICAgICAgICBib3JkZXItcmFkaXVzOiA1MCU7XG4gICAgICAgIGFuaW1hdGlvbjogc3BpbiAwLjhzIGxpbmVhciBpbmZpbml0ZTtcbiAgICAgIH1cblxuICAgICAgQGtleWZyYW1lcyBzcGluIHtcbiAgICAgICAgdG8geyB0cmFuc2Zvcm06IHJvdGF0ZSgzNjBkZWcpOyB9XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1sb2FkaW5nLXRleHQge1xuICAgICAgICBtYXJnaW4tdG9wOiAxMnB4O1xuICAgICAgICBmb250LXNpemU6IDE0cHg7XG4gICAgICAgIGNvbG9yOiAjNmI3MjgwO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtaWZyYW1lIHtcbiAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgICB0b3A6IC0xMzZweDtcbiAgICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICAgIGhlaWdodDogY2FsYygxMDAlICsgMTM2cHgpO1xuICAgICAgICBib3JkZXI6IG5vbmU7XG4gICAgICAgIHRyYW5zaXRpb246IG9wYWNpdHkgMC4zcyBlYXNlO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtZGFyayAub3BlbmNvZGUtY2hhdCB7XG4gICAgICAgIGJhY2tncm91bmQ6ICMxYTFhMWE7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1kYXJrIC5vcGVuY29kZS1zZXNzaW9uLWxpc3Qge1xuICAgICAgICBiYWNrZ3JvdW5kOiAjMTExODI3O1xuICAgICAgICBib3JkZXItcmlnaHQtY29sb3I6ICMzNzQxNTE7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1kYXJrIC5vcGVuY29kZS1zZXNzaW9uLXRvZ2dsZSB7XG4gICAgICAgIGNvbG9yOiAjOWNhM2FmO1xuICAgICAgICBib3JkZXItYm90dG9tLWNvbG9yOiAjMzc0MTUxO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtZGFyayAub3BlbmNvZGUtc2Vzc2lvbi10b2dnbGU6aG92ZXIge1xuICAgICAgICBiYWNrZ3JvdW5kOiAjMzc0MTUxO1xuICAgICAgICBjb2xvcjogI2YzZjRmNjtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWRhcmsgLm9wZW5jb2RlLXNlc3Npb24tbGlzdC1oZWFkZXIge1xuICAgICAgICBib3JkZXItYm90dG9tLWNvbG9yOiAjMzc0MTUxO1xuICAgICAgICBjb2xvcjogI2YzZjRmNjtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWRhcmsgLm9wZW5jb2RlLXNlc3Npb24taXRlbTpob3ZlciB7XG4gICAgICAgIGJhY2tncm91bmQ6ICMzNzQxNTE7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1kYXJrIC5vcGVuY29kZS1zZXNzaW9uLWl0ZW0uYWN0aXZlIHtcbiAgICAgICAgYmFja2dyb3VuZDogIzNiODJmNjtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWRhcmsgLm9wZW5jb2RlLWxvYWRpbmctb3ZlcmxheSB7XG4gICAgICAgIGJhY2tncm91bmQ6IHJnYmEoMjYsIDI2LCAyNiwgMC45KTtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWRhcmsgLm9wZW5jb2RlLWxvYWRpbmctc3Bpbm5lciB7XG4gICAgICAgIGJvcmRlci1jb2xvcjogIzM3NDE1MTtcbiAgICAgICAgYm9yZGVyLXRvcC1jb2xvcjogIzNiODJmNjtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWRhcmsgLm9wZW5jb2RlLWxvYWRpbmctdGV4dCB7XG4gICAgICAgIGNvbG9yOiAjOWNhM2FmO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtcmlnaHQtdG9vbGJhciB7XG4gICAgICAgIHdpZHRoOiAxNDBweDtcbiAgICAgICAgYmFja2dyb3VuZDogI2Y4ZjlmYTtcbiAgICAgICAgYm9yZGVyLWxlZnQ6IDFweCBzb2xpZCAjZTVlN2ViO1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgICBmbGV4LXNocmluazogMDtcbiAgICAgICAgdHJhbnNpdGlvbjogd2lkdGggMC4ycyBlYXNlO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtcmlnaHQtdG9vbGJhci5jb2xsYXBzZWQge1xuICAgICAgICB3aWR0aDogNDBweDtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLXJpZ2h0LXRvb2xiYXIuY29sbGFwc2VkIC5vcGVuY29kZS1zZWxlY3RlZC1ub2RlcyB7XG4gICAgICAgIGRpc3BsYXk6IG5vbmU7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1zZWxlY3QtYnRuIHtcbiAgICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICAgIGhlaWdodDogNDRweDtcbiAgICAgICAgYm9yZGVyOiBub25lO1xuICAgICAgICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcbiAgICAgICAgY29sb3I6ICM2YjcyODA7XG4gICAgICAgIGN1cnNvcjogcG9pbnRlcjtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gICAgICAgIGdhcDogOHB4O1xuICAgICAgICB0cmFuc2l0aW9uOiBhbGwgMC4ycztcbiAgICAgICAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICNlNWU3ZWI7XG4gICAgICAgIGZvbnQtc2l6ZTogMTNweDtcbiAgICAgICAgZm9udC13ZWlnaHQ6IDUwMDtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLXNlbGVjdC1idG46aG92ZXIge1xuICAgICAgICBiYWNrZ3JvdW5kOiAjZTVlN2ViO1xuICAgICAgICBjb2xvcjogIzM3NDE1MTtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLXNlbGVjdC1idG4uYWN0aXZlIHtcbiAgICAgICAgYmFja2dyb3VuZDogIzNiODJmNjtcbiAgICAgICAgY29sb3I6IHdoaXRlO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtc2VsZWN0ZWQtbm9kZXMge1xuICAgICAgICBmbGV4OiAxO1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgICBwYWRkaW5nOiA4cHg7XG4gICAgICAgIGdhcDogNnB4O1xuICAgICAgICBvdmVyZmxvdy15OiBhdXRvO1xuICAgICAgICBvdmVyZmxvdy14OiBoaWRkZW47XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1zZWxlY3RlZC1ub2RlczplbXB0eTo6YmVmb3JlIHtcbiAgICAgICAgY29udGVudDogJ+aaguaXoOmAieS4reWFg+e0oCc7XG4gICAgICAgIGNvbG9yOiAjOWNhM2FmO1xuICAgICAgICBmb250LXNpemU6IDEycHg7XG4gICAgICAgIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgICAgICAgcGFkZGluZzogMjBweCAxMHB4O1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtc2VsZWN0ZWQtbm9kZSB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICAgIGdhcDogOHB4O1xuICAgICAgICBwYWRkaW5nOiA4cHggMTBweDtcbiAgICAgICAgYmFja2dyb3VuZDogd2hpdGU7XG4gICAgICAgIGJvcmRlcjogMXB4IHNvbGlkICNlNWU3ZWI7XG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDZweDtcbiAgICAgICAgZm9udC1zaXplOiAxMnB4O1xuICAgICAgICB0cmFuc2l0aW9uOiBhbGwgMC4ycztcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLXNlbGVjdGVkLW5vZGU6aG92ZXIge1xuICAgICAgICBib3JkZXItY29sb3I6ICMzYjgyZjY7XG4gICAgICAgIGJveC1zaGFkb3c6IDAgMnB4IDRweCByZ2JhKDU5LCAxMzAsIDI0NiwgMC4xKTtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLW5vZGUtY29udGVudCB7XG4gICAgICAgIGZsZXg6IDE7XG4gICAgICAgIG1pbi13aWR0aDogMDtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICAgICAgZ2FwOiAycHg7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1ub2RlLXRleHQge1xuICAgICAgICBjb2xvcjogIzM3NDE1MTtcbiAgICAgICAgZm9udC13ZWlnaHQ6IDUwMDtcbiAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgICAgICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XG4gICAgICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1ub2RlLWZpbGUge1xuICAgICAgICBjb2xvcjogIzljYTNhZjtcbiAgICAgICAgZm9udC1zaXplOiAxMXB4O1xuICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgICAgICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcbiAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLW5vZGUtcmVtb3ZlIHtcbiAgICAgICAgd2lkdGg6IDE4cHg7XG4gICAgICAgIGhlaWdodDogMThweDtcbiAgICAgICAgYm9yZGVyLXJhZGl1czogNHB4O1xuICAgICAgICBib3JkZXI6IG5vbmU7XG4gICAgICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xuICAgICAgICBjb2xvcjogIzljYTNhZjtcbiAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgICAgICAgZm9udC1zaXplOiAxNHB4O1xuICAgICAgICB0cmFuc2l0aW9uOiBhbGwgMC4ycztcbiAgICAgICAgZmxleC1zaHJpbms6IDA7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1ub2RlLXJlbW92ZTpob3ZlciB7XG4gICAgICAgIGJhY2tncm91bmQ6ICNlZjQ0NDQ7XG4gICAgICAgIGNvbG9yOiB3aGl0ZTtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWRhcmsgLm9wZW5jb2RlLXJpZ2h0LXRvb2xiYXIge1xuICAgICAgICBiYWNrZ3JvdW5kOiAjMTExODI3O1xuICAgICAgICBib3JkZXItbGVmdC1jb2xvcjogIzM3NDE1MTtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWRhcmsgLm9wZW5jb2RlLXNlbGVjdC1idG4ge1xuICAgICAgICBjb2xvcjogIzljYTNhZjtcbiAgICAgICAgYm9yZGVyLWJvdHRvbS1jb2xvcjogIzM3NDE1MTtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWRhcmsgLm9wZW5jb2RlLXNlbGVjdC1idG46aG92ZXIge1xuICAgICAgICBiYWNrZ3JvdW5kOiAjMzc0MTUxO1xuICAgICAgICBjb2xvcjogI2YzZjRmNjtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWRhcmsgLm9wZW5jb2RlLXNlbGVjdGVkLW5vZGVzOmVtcHR5OjpiZWZvcmUge1xuICAgICAgICBjb2xvcjogIzZiNzI4MDtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWRhcmsgLm9wZW5jb2RlLXNlbGVjdGVkLW5vZGUge1xuICAgICAgICBiYWNrZ3JvdW5kOiAjMWYyOTM3O1xuICAgICAgICBib3JkZXItY29sb3I6ICMzNzQxNTE7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1kYXJrIC5vcGVuY29kZS1zZWxlY3RlZC1ub2RlOmhvdmVyIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiAjM2I4MmY2O1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtZGFyayAub3BlbmNvZGUtbm9kZS10ZXh0IHtcbiAgICAgICAgY29sb3I6ICNmM2Y0ZjY7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1kYXJrIC5vcGVuY29kZS1ub2RlLWZpbGUge1xuICAgICAgICBjb2xvcjogIzZiNzI4MDtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWRhcmsgLm9wZW5jb2RlLW5vZGUtcmVtb3ZlIHtcbiAgICAgICAgY29sb3I6ICM2YjcyODA7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1kYXJrIC5vcGVuY29kZS1ub2RlLXJlbW92ZTpob3ZlciB7XG4gICAgICAgIGJhY2tncm91bmQ6ICNlZjQ0NDQ7XG4gICAgICAgIGNvbG9yOiB3aGl0ZTtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWRhcmsgLm9wZW5jb2RlLWJ1dHRvbiB7XG4gICAgICAgIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICM2NjdlZWEgMCUsICM3NjRiYTIgMTAwJSk7XG4gICAgICAgIGJveC1zaGFkb3c6IDAgNHB4IDE1cHggcmdiYSgxMDIsIDEyNiwgMjM0LCAwLjUpO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtbm90aWZpY2F0aW9uIHtcbiAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgICB0b3A6IDIwcHg7XG4gICAgICAgIGxlZnQ6IDUwJTtcbiAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKC01MCUpO1xuICAgICAgICBwYWRkaW5nOiAxMnB4IDIwcHg7XG4gICAgICAgIGJhY2tncm91bmQ6ICMxMGI5ODE7XG4gICAgICAgIGNvbG9yOiB3aGl0ZTtcbiAgICAgICAgYm9yZGVyLXJhZGl1czogOHB4O1xuICAgICAgICBmb250LXNpemU6IDE0cHg7XG4gICAgICAgIGJveC1zaGFkb3c6IDAgNHB4IDEycHggcmdiYSgwLCAwLCAwLCAwLjE1KTtcbiAgICAgICAgYW5pbWF0aW9uOiBzbGlkZURvd24gMC4zcyBlYXNlO1xuICAgICAgICB6LWluZGV4OiAxMDtcbiAgICAgIH1cblxuICAgICAgQGtleWZyYW1lcyBzbGlkZURvd24ge1xuICAgICAgICBmcm9tIHtcbiAgICAgICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSkgdHJhbnNsYXRlWSgtMTAwJSk7XG4gICAgICAgICAgb3BhY2l0eTogMDtcbiAgICAgICAgfVxuICAgICAgICB0byB7XG4gICAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKC01MCUpIHRyYW5zbGF0ZVkoMCk7XG4gICAgICAgICAgb3BhY2l0eTogMTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtc2VsZWN0LW1vZGUtaGludCB7XG4gICAgICAgIHBvc2l0aW9uOiBmaXhlZDtcbiAgICAgICAgdG9wOiAyMHB4O1xuICAgICAgICBsZWZ0OiA1MCU7XG4gICAgICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWCgtNTAlKTtcbiAgICAgICAgcGFkZGluZzogMTBweCAxNnB4O1xuICAgICAgICBiYWNrZ3JvdW5kOiAjM2I4MmY2O1xuICAgICAgICBjb2xvcjogd2hpdGU7XG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDhweDtcbiAgICAgICAgZm9udC1zaXplOiAxM3B4O1xuICAgICAgICBib3gtc2hhZG93OiAwIDRweCAxMnB4IHJnYmEoNTksIDEzMCwgMjQ2LCAwLjMpO1xuICAgICAgICB6LWluZGV4OiA5OTk5OTk5O1xuICAgICAgICBkaXNwbGF5OiBub25lO1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBnYXA6IDEycHg7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1zZWxlY3QtbW9kZS1oaW50LnZpc2libGUge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBhbmltYXRpb246IHNsaWRlRG93biAwLjNzIGVhc2U7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1oaW50LXNob3J0Y3V0IHtcbiAgICAgICAgcGFkZGluZzogMnB4IDZweDtcbiAgICAgICAgYmFja2dyb3VuZDogcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjIpO1xuICAgICAgICBib3JkZXItcmFkaXVzOiA0cHg7XG4gICAgICAgIGZvbnQtc2l6ZTogMTJweDtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLXNlbGVjdGVkLWJ1YmJsZXMge1xuICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICAgIGJvdHRvbTogNzBweDtcbiAgICAgICAgcmlnaHQ6IDA7XG4gICAgICAgIGRpc3BsYXk6IG5vbmU7XG4gICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgICAgIGdhcDogNnB4O1xuICAgICAgICBtYXgtd2lkdGg6IDIyMHB4O1xuICAgICAgICBtYXgtaGVpZ2h0OiAzMDBweDtcbiAgICAgICAgb3ZlcmZsb3cteTogYXV0bztcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLXNlbGVjdGVkLWJ1YmJsZXMudmlzaWJsZSB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1zZWxlY3RlZC1idWJibGUge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgICBnYXA6IDJweDtcbiAgICAgICAgcGFkZGluZzogOHB4IDEwcHg7XG4gICAgICAgIGJhY2tncm91bmQ6IHdoaXRlO1xuICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjZTVlN2ViO1xuICAgICAgICBib3JkZXItcmFkaXVzOiA4cHg7XG4gICAgICAgIGZvbnQtc2l6ZTogMTJweDtcbiAgICAgICAgYm94LXNoYWRvdzogMCAycHggOHB4IHJnYmEoMCwgMCwgMCwgMC4xKTtcbiAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtYnViYmxlLXRleHQge1xuICAgICAgICBjb2xvcjogIzM3NDE1MTtcbiAgICAgICAgZm9udC13ZWlnaHQ6IDUwMDtcbiAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgICAgICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XG4gICAgICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1idWJibGUtZmlsZSB7XG4gICAgICAgIGNvbG9yOiAjOWNhM2FmO1xuICAgICAgICBmb250LXNpemU6IDExcHg7XG4gICAgICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgICAgIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xuICAgICAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtYnViYmxlLXJlbW92ZSB7XG4gICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgICAgdG9wOiA0cHg7XG4gICAgICAgIHJpZ2h0OiA0cHg7XG4gICAgICAgIHdpZHRoOiAxNnB4O1xuICAgICAgICBoZWlnaHQ6IDE2cHg7XG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcbiAgICAgICAgYm9yZGVyOiBub25lO1xuICAgICAgICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcbiAgICAgICAgY29sb3I6ICM5Y2EzYWY7XG4gICAgICAgIGN1cnNvcjogcG9pbnRlcjtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gICAgICAgIGZvbnQtc2l6ZTogMTJweDtcbiAgICAgICAgdHJhbnNpdGlvbjogYWxsIDAuMnM7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1idWJibGUtcmVtb3ZlOmhvdmVyIHtcbiAgICAgICAgYmFja2dyb3VuZDogI2VmNDQ0NDtcbiAgICAgICAgY29sb3I6IHdoaXRlO1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtYnViYmxlLWVtcHR5IHtcbiAgICAgICAgcGFkZGluZzogOHB4IDEycHg7XG4gICAgICAgIGJhY2tncm91bmQ6IHdoaXRlO1xuICAgICAgICBib3JkZXI6IDFweCBkYXNoZWQgI2QxZDVkYjtcbiAgICAgICAgYm9yZGVyLXJhZGl1czogOHB4O1xuICAgICAgICBjb2xvcjogIzljYTNhZjtcbiAgICAgICAgZm9udC1zaXplOiAxMnB4O1xuICAgICAgICB0ZXh0LWFsaWduOiBjZW50ZXI7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1kYXJrIC5vcGVuY29kZS1zZWxlY3RlZC1idWJibGUge1xuICAgICAgICBiYWNrZ3JvdW5kOiAjMWYyOTM3O1xuICAgICAgICBib3JkZXItY29sb3I6ICMzNzQxNTE7XG4gICAgICB9XG5cbiAgICAgIC5vcGVuY29kZS1kYXJrIC5vcGVuY29kZS1idWJibGUtdGV4dCB7XG4gICAgICAgIGNvbG9yOiAjZjNmNGY2O1xuICAgICAgfVxuXG4gICAgICAub3BlbmNvZGUtZGFyayAub3BlbmNvZGUtYnViYmxlLWZpbGUge1xuICAgICAgICBjb2xvcjogIzZiNzI4MDtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWRhcmsgLm9wZW5jb2RlLWJ1YmJsZS1yZW1vdmUge1xuICAgICAgICBjb2xvcjogIzZiNzI4MDtcbiAgICAgIH1cblxuICAgICAgLm9wZW5jb2RlLWRhcmsgLm9wZW5jb2RlLWJ1YmJsZS1lbXB0eSB7XG4gICAgICAgIGJhY2tncm91bmQ6ICMxZjI5Mzc7XG4gICAgICAgIGJvcmRlci1jb2xvcjogIzM3NDE1MTtcbiAgICAgICAgY29sb3I6ICM2YjcyODA7XG4gICAgICB9XG5cbiAgICAgIEBtZWRpYSAobWF4LXdpZHRoOiA3NjhweCkge1xuICAgICAgICAub3BlbmNvZGUtY2hhdCB7XG4gICAgICAgICAgd2lkdGg6IGNhbGMoMTAwdncgLSA0MHB4KTtcbiAgICAgICAgICBoZWlnaHQ6IGNhbGMoMTAwdmggLSAxMjBweCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICBgXG4gIH1cblxuICAvKipcbiAgICog6Ieq5Yqo5Yid5aeL5YyW5oyC5Lu2XG4gICAqL1xuICBmdW5jdGlvbiBhdXRvSW5pdCgpIHtcbiAgICBjb25zdCBzY3JpcHQgPSBkb2N1bWVudC5jdXJyZW50U2NyaXB0IHx8IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3NjcmlwdFtkYXRhLW9wZW5jb2RlLWNvbmZpZ10nKVxuICAgIGlmIChzY3JpcHQpIHtcbiAgICAgIGNvbnN0IGNvbmZpZ0Jhc2U2NCA9IHNjcmlwdC5nZXRBdHRyaWJ1dGUoJ2RhdGEtb3BlbmNvZGUtY29uZmlnJylcbiAgICAgIGlmIChjb25maWdCYXNlNjQpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBjb25maWcgPSBKU09OLnBhcnNlKGF0b2IoY29uZmlnQmFzZTY0KSlcbiAgICAgICAgICBpZiAoZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ2xvYWRpbmcnKSB7XG4gICAgICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIGluaXRPcGVuQ29kZVdpZGdldChjb25maWcpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpbml0T3BlbkNvZGVXaWRnZXQoY29uZmlnKVxuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1tPcGVuQ29kZSBXaWRnZXRdIEZhaWxlZCB0byBwYXJzZSBjb25maWc6JywgZSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIOWvvOWHuuWFqOWxgOWIneWni+WMluWHveaVsFxuICB3aW5kb3cuaW5pdE9wZW5Db2RlV2lkZ2V0ID0gaW5pdE9wZW5Db2RlV2lkZ2V0XG5cbiAgLy8g6Ieq5Yqo5Yid5aeL5YyWXG4gIGF1dG9Jbml0KClcbn0pKCk7Il19