tool-dom-ang15 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/esm2020/lib/dom/dom-tools.mjs +31 -0
- package/esm2020/lib/dom/source/dom-class.mjs +198 -0
- package/esm2020/lib/dom/source/dom-element.mjs +299 -0
- package/esm2020/lib/dom/source/dom-style.mjs +31 -0
- package/esm2020/lib/dom/source/dom.interface.mjs +2 -0
- package/esm2020/lib/tool-dom-ang15.component.mjs +43 -51
- package/esm2020/public-api.mjs +2 -5
- package/fesm2015/tool-dom-ang15.mjs +73 -66
- package/fesm2015/tool-dom-ang15.mjs.map +1 -1
- package/fesm2020/tool-dom-ang15.mjs +70 -63
- package/fesm2020/tool-dom-ang15.mjs.map +1 -1
- package/lib/dom/dom-tools.d.ts +18 -0
- package/lib/dom/{dom-class.d.ts → source/dom-class.d.ts} +1 -1
- package/lib/tool-dom-ang15.component.d.ts +2 -9
- package/package.json +1 -1
- package/public-api.d.ts +1 -4
- package/esm2020/lib/dom/dom-class.mjs +0 -198
- package/esm2020/lib/dom/dom-element.mjs +0 -299
- package/esm2020/lib/dom/dom-style.mjs +0 -31
- package/esm2020/lib/dom/dom.interface.mjs +0 -2
- package/esm2020/lib/tool-dom-ang15.service.mjs +0 -15
- package/lib/tool-dom-ang15.service.d.ts +0 -6
- /package/lib/dom/{dom-element.d.ts → source/dom-element.d.ts} +0 -0
- /package/lib/dom/{dom-style.d.ts → source/dom-style.d.ts} +0 -0
- /package/lib/dom/{dom.interface.d.ts → source/dom.interface.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -52,9 +52,11 @@ tool-dom-ang15/
|
|
|
52
52
|
├── tool-dom-ang15.component.html # шаблон (панели + лог)
|
|
53
53
|
├── tool-dom-ang15.component.scss # стили
|
|
54
54
|
└── dom/
|
|
55
|
-
├── dom-
|
|
56
|
-
├──
|
|
57
|
-
|
|
55
|
+
├── dom-tools.ts # сервис DomToolsService
|
|
56
|
+
├── root
|
|
57
|
+
├── dom-element.ts # сервис DomElement
|
|
58
|
+
├── dom-class.ts # сервис DomClass
|
|
59
|
+
└── dom-style.ts # сервис DomStyle
|
|
58
60
|
```
|
|
59
61
|
|
|
60
62
|
---
|
|
@@ -95,7 +97,7 @@ tool-dom-ang15/
|
|
|
95
97
|
**Инициализация (`ngOnInit`):**
|
|
96
98
|
|
|
97
99
|
```ts
|
|
98
|
-
this.
|
|
100
|
+
this.elt = new DomElement(this.document);
|
|
99
101
|
this.cls = new DomClass(this.document);
|
|
100
102
|
this.style = new DomStyle();
|
|
101
103
|
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Inject, Injectable } from '@angular/core';
|
|
2
|
+
import { DOCUMENT } from '@angular/common';
|
|
3
|
+
import { DomClass } from './source/dom-class';
|
|
4
|
+
import { DomElement } from './source/dom-element';
|
|
5
|
+
import { DomStyle } from './source/dom-style';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
export function createDomTools(document) {
|
|
8
|
+
return {
|
|
9
|
+
elt: new DomElement(document),
|
|
10
|
+
cls: new DomClass(document),
|
|
11
|
+
style: new DomStyle(),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export class DomToolsService {
|
|
15
|
+
constructor(document) {
|
|
16
|
+
const t = createDomTools(document);
|
|
17
|
+
this.elt = t.elt;
|
|
18
|
+
this.cls = t.cls;
|
|
19
|
+
this.style = t.style;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
DomToolsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DomToolsService, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
23
|
+
DomToolsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DomToolsService, providedIn: 'root' });
|
|
24
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DomToolsService, decorators: [{
|
|
25
|
+
type: Injectable,
|
|
26
|
+
args: [{ providedIn: 'root' }]
|
|
27
|
+
}], ctorParameters: function () { return [{ type: Document, decorators: [{
|
|
28
|
+
type: Inject,
|
|
29
|
+
args: [DOCUMENT]
|
|
30
|
+
}] }]; } });
|
|
31
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9tLXRvb2xzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdG9vbC1kb20tYW5nMTUvc3JjL2xpYi9kb20vZG9tLXRvb2xzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUUxQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDOUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQzs7QUFROUMsTUFBTSxVQUFVLGNBQWMsQ0FBQyxRQUFrQjtJQUM3QyxPQUFPO1FBQ0gsR0FBRyxFQUFFLElBQUksVUFBVSxDQUFDLFFBQVEsQ0FBQztRQUM3QixHQUFHLEVBQUUsSUFBSSxRQUFRLENBQUMsUUFBUSxDQUFDO1FBQzNCLEtBQUssRUFBRSxJQUFJLFFBQVEsRUFBRTtLQUN4QixDQUFDO0FBQ04sQ0FBQztBQUdELE1BQU0sT0FBTyxlQUFlO0lBS3hCLFlBQThCLFFBQWtCO1FBQzVDLE1BQU0sQ0FBQyxHQUFHLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNuQyxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDakIsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDO1FBQ2pCLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQztJQUN6QixDQUFDOzs2R0FWUSxlQUFlLGtCQUtKLFFBQVE7aUhBTG5CLGVBQWUsY0FESCxNQUFNOzRGQUNsQixlQUFlO2tCQUQzQixVQUFVO21CQUFDLEVBQUMsVUFBVSxFQUFFLE1BQU0sRUFBQzs7MEJBTWYsTUFBTTsyQkFBQyxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IERPQ1VNRU5UIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJ1xyXG5cclxuaW1wb3J0IHsgRG9tQ2xhc3MgfSBmcm9tICcuL3NvdXJjZS9kb20tY2xhc3MnO1xyXG5pbXBvcnQgeyBEb21FbGVtZW50IH0gZnJvbSAnLi9zb3VyY2UvZG9tLWVsZW1lbnQnO1xyXG5pbXBvcnQgeyBEb21TdHlsZSB9IGZyb20gJy4vc291cmNlL2RvbS1zdHlsZSc7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIERvbVRvb2xzIHtcclxuICAgIGVsdDogRG9tRWxlbWVudDtcclxuICAgIGNsczogRG9tQ2xhc3M7XHJcbiAgICBzdHlsZTogRG9tU3R5bGU7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVEb21Ub29scyhkb2N1bWVudDogRG9jdW1lbnQpOiBEb21Ub29scyB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIGVsdDogbmV3IERvbUVsZW1lbnQoZG9jdW1lbnQpLFxyXG4gICAgICAgIGNsczogbmV3IERvbUNsYXNzKGRvY3VtZW50KSxcclxuICAgICAgICBzdHlsZTogbmV3IERvbVN0eWxlKCksXHJcbiAgICB9O1xyXG59XHJcblxyXG5ASW5qZWN0YWJsZSh7cHJvdmlkZWRJbjogJ3Jvb3QnfSlcclxuZXhwb3J0IGNsYXNzIERvbVRvb2xzU2VydmljZSB7XHJcbiAgICByZWFkb25seSBlbHQ6IERvbUVsZW1lbnQ7XHJcbiAgICByZWFkb25seSBjbHM6IERvbUNsYXNzO1xyXG4gICAgcmVhZG9ubHkgc3R5bGU6IERvbVN0eWxlO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKEBJbmplY3QoRE9DVU1FTlQpIGRvY3VtZW50OiBEb2N1bWVudCkge1xyXG4gICAgICAgIGNvbnN0IHQgPSBjcmVhdGVEb21Ub29scyhkb2N1bWVudCk7XHJcbiAgICAgICAgdGhpcy5lbHQgPSB0LmVsdDtcclxuICAgICAgICB0aGlzLmNscyA9IHQuY2xzO1xyXG4gICAgICAgIHRoaXMuc3R5bGUgPSB0LnN0eWxlO1xyXG4gICAgfVxyXG59XHJcbiJdfQ==
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { __decorate, __param } from "tslib";
|
|
2
|
+
import { Inject } from '@angular/core';
|
|
3
|
+
import { DOCUMENT } from "@angular/common";
|
|
4
|
+
import { DomElement } from "./dom-element";
|
|
5
|
+
/**
|
|
6
|
+
* Класс для работы с классами DOM
|
|
7
|
+
*/
|
|
8
|
+
let DomClass = class DomClass {
|
|
9
|
+
constructor(document) {
|
|
10
|
+
this.document = document;
|
|
11
|
+
this.elt = new DomElement(this.document);
|
|
12
|
+
}
|
|
13
|
+
//region Управление классами
|
|
14
|
+
/**
|
|
15
|
+
* Проверяет наличие класса у элемента
|
|
16
|
+
*
|
|
17
|
+
* @param {HTMLElement} element - Элемент
|
|
18
|
+
* @param {string} className - Класс
|
|
19
|
+
*
|
|
20
|
+
* @returns {boolean} true, если класс присутствует
|
|
21
|
+
*/
|
|
22
|
+
hasClass(element, className) {
|
|
23
|
+
return !!(className && element?.classList.contains(className));
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Добавляет класс элементу
|
|
27
|
+
*
|
|
28
|
+
* @param {HTMLElement} element - Элемент
|
|
29
|
+
* @param {string} className - Класс
|
|
30
|
+
*
|
|
31
|
+
* @returns {boolean} true, если класс добавили
|
|
32
|
+
*/
|
|
33
|
+
addClass(element, className) {
|
|
34
|
+
if (className && element && 'classList' in element) {
|
|
35
|
+
element.classList.add(className);
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Массовое добавление CSS-классов
|
|
42
|
+
*
|
|
43
|
+
* @param {HTMLElement} element - Элемент
|
|
44
|
+
* @param classNames - Массив названий CSS-классов для добавления
|
|
45
|
+
*/
|
|
46
|
+
addClasses(element, classNames) {
|
|
47
|
+
if (!element || !classNames || classNames.length === 0) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
classNames.forEach(className => {
|
|
51
|
+
if (className && className.trim() !== '') {
|
|
52
|
+
this.addClass(element, className.trim());
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Создает CSS-классы для margin и padding на основе переменных --evo{n}.
|
|
58
|
+
* Классы генерируются для всех направлений (top, right, bottom, left).
|
|
59
|
+
*
|
|
60
|
+
* @param elementRef - Элемент для которого будут создаваться классы.
|
|
61
|
+
* @param {number[]} arrVars - Значения для генерации классов.
|
|
62
|
+
*
|
|
63
|
+
*/
|
|
64
|
+
addClassMarginPadding(elementRef, arrVars = []) {
|
|
65
|
+
const root = this.elt.elementGetParent(elementRef.nativeElement);
|
|
66
|
+
if (!root) {
|
|
67
|
+
console.error('Root element not found');
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const properties = ['m', 'p']; // margin, padding
|
|
71
|
+
const directions = ['t', 'r', 'b', 'l']; // top, right, bottom, left
|
|
72
|
+
let style = this.document.querySelector('style[data-dynamic-style]');
|
|
73
|
+
if (!style) {
|
|
74
|
+
style = this.document.createElement('style');
|
|
75
|
+
style.setAttribute('data-dynamic-style', '');
|
|
76
|
+
root.appendChild(style);
|
|
77
|
+
}
|
|
78
|
+
let cssContent = '';
|
|
79
|
+
// Добавляем классы для arrVars (если массив не пустой)
|
|
80
|
+
if (arrVars && arrVars.length > 0) {
|
|
81
|
+
arrVars.forEach(value => {
|
|
82
|
+
properties.forEach(prop => {
|
|
83
|
+
directions.forEach(dir => {
|
|
84
|
+
const className = `.evo-${prop}${dir}-${value}`;
|
|
85
|
+
const cssProperty = prop === 'm' ? 'margin' : 'padding';
|
|
86
|
+
const cssDirection = this._getCssDirection(dir);
|
|
87
|
+
cssContent += `${className} { ${cssProperty}-${cssDirection}: var(--evo${value}); }\n`;
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
style.textContent = cssContent;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Удаление всех классов созданных в addClassMarginPadding (<style data-dynamic-style="">)
|
|
96
|
+
* @see {@link addClassMarginPadding} - Создает CSS-классы для margin и padding на основе переменных --evo{n}.
|
|
97
|
+
*/
|
|
98
|
+
deleteClassMarginPadding() {
|
|
99
|
+
this.document.querySelector('style[data-dynamic-style]')?.remove();
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Удаляет класс у элемента
|
|
103
|
+
*
|
|
104
|
+
* @param {HTMLElement} element - Элемент
|
|
105
|
+
* @param {string} className - Класс
|
|
106
|
+
*
|
|
107
|
+
* @returns {boolean} true, если класс был удален
|
|
108
|
+
*/
|
|
109
|
+
removeClass(element, className) {
|
|
110
|
+
if (className && element && 'classList' in element) {
|
|
111
|
+
element.classList.remove(className);
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Переключает CSS-класс у корневого элемента
|
|
118
|
+
*
|
|
119
|
+
* @param {HTMLElement} element - Элемент
|
|
120
|
+
* @param className - Название CSS-класса для переключения
|
|
121
|
+
* @param force - Принудительно установить или удалить класс (true - добавить, false - удалить)
|
|
122
|
+
*/
|
|
123
|
+
toggleClass(element, className, force) {
|
|
124
|
+
if (!element || !className) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const trimmedClassName = className.trim();
|
|
128
|
+
if (force !== undefined) {
|
|
129
|
+
if (force) {
|
|
130
|
+
this.addClass(element, trimmedClassName);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
this.removeClass(element, trimmedClassName);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
// Переключаем на основе текущего состояния
|
|
138
|
+
if (this.hasClass(element, trimmedClassName)) {
|
|
139
|
+
this.removeClass(element, trimmedClassName);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
this.addClass(element, trimmedClassName);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Возвращает массив всех CSS-классов корневого элемента
|
|
148
|
+
*
|
|
149
|
+
* @param {HTMLElement} element - Элемент
|
|
150
|
+
*
|
|
151
|
+
* @returns Массив названий CSS-классов
|
|
152
|
+
*/
|
|
153
|
+
getClasses(element) {
|
|
154
|
+
if (element) {
|
|
155
|
+
// Получаем актуальные классы с элемента
|
|
156
|
+
return Array.from(element.classList);
|
|
157
|
+
}
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Удаляет все CSS-классы у корневого элемента и очищает кэш
|
|
162
|
+
*
|
|
163
|
+
* @param {HTMLElement} element - Элемент
|
|
164
|
+
*/
|
|
165
|
+
clearClasses(element) {
|
|
166
|
+
// Удаляем все классы с элемента
|
|
167
|
+
if (element) {
|
|
168
|
+
element.className = '';
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//endregion
|
|
172
|
+
//region Приватные методы
|
|
173
|
+
/**
|
|
174
|
+
* Преобразует сокращенное направление (t, r, b, l) в полное название CSS-свойства.
|
|
175
|
+
*
|
|
176
|
+
* @param {string} dir - Сокращенное направление (t, r, b, l).
|
|
177
|
+
* @returns {string} Полное название направления (top, right, bottom, left).
|
|
178
|
+
*/
|
|
179
|
+
_getCssDirection(dir) {
|
|
180
|
+
switch (dir) {
|
|
181
|
+
case 't':
|
|
182
|
+
return 'top';
|
|
183
|
+
case 'r':
|
|
184
|
+
return 'right';
|
|
185
|
+
case 'b':
|
|
186
|
+
return 'bottom';
|
|
187
|
+
case 'l':
|
|
188
|
+
return 'left';
|
|
189
|
+
default:
|
|
190
|
+
return '';
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
DomClass = __decorate([
|
|
195
|
+
__param(0, Inject(DOCUMENT))
|
|
196
|
+
], DomClass);
|
|
197
|
+
export { DomClass };
|
|
198
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9tLWNsYXNzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdG9vbC1kb20tYW5nMTUvc3JjL2xpYi9kb20vc291cmNlL2RvbS1jbGFzcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFhLE1BQU0sRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUNqRCxPQUFPLEVBQUMsUUFBUSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDekMsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUV6Qzs7R0FFRztBQUNJLElBQU0sUUFBUSxHQUFkLE1BQU0sUUFBUTtJQUdqQixZQUM2QixRQUFrQjtRQUFsQixhQUFRLEdBQVIsUUFBUSxDQUFVO1FBRTNDLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBQzVDLENBQUM7SUFFRCw0QkFBNEI7SUFDNUI7Ozs7Ozs7T0FPRztJQUNILFFBQVEsQ0FBQyxPQUFvQixFQUFFLFNBQWlCO1FBQzVDLE9BQU8sQ0FBQyxDQUFDLENBQUMsU0FBUyxJQUFJLE9BQU8sRUFBRSxTQUFTLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDbkUsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxRQUFRLENBQUMsT0FBMkIsRUFBRSxTQUFpQjtRQUNuRCxJQUFJLFNBQVMsSUFBSSxPQUFPLElBQUksV0FBVyxJQUFJLE9BQU8sRUFBRTtZQUNoRCxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUVqQyxPQUFPLElBQUksQ0FBQztTQUNmO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDakIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsVUFBVSxDQUFDLE9BQTJCLEVBQUUsVUFBb0I7UUFDeEQsSUFBSSxDQUFDLE9BQU8sSUFBSSxDQUFDLFVBQVUsSUFB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QUssR0FBRztnQkFDSixPQUFPLEtBQUssQ0FBQztZQUNqQixLQUFLLEdBQUc7Z0JBQ0osT0FBTyxPQUFPLENBQUM7WUFDbkIsS0FBSyxHQUFHO2dCQUNKLE9BQU8sUUFBUSxDQUFDO1lBQ3BCLEtBQUssR0FBRztnQkFDSixPQUFPLE1BQU0sQ0FBQztZQUNsQjtnQkFDSSxPQUFPLEVBQUUsQ0FBQztTQUNqQjtJQUNMLENBQUM7Q0FHSixDQUFBO0FBdE5ZLFFBQVE7SUFJWixXQUFBLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQTtHQUpaLFFBQVEsQ0FzTnBCO1NBdE5ZLFFBQVEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0VsZW1lbnRSZWYsIEluamVjdH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7RE9DVU1FTlR9IGZyb20gXCJAYW5ndWxhci9jb21tb25cIjtcclxuaW1wb3J0IHtEb21FbGVtZW50fSBmcm9tIFwiLi9kb20tZWxlbWVudFwiO1xyXG5cclxuLyoqXHJcbiAqINCa0LvQsNGB0YEg0LTQu9GPINGA0LDQsdC+0YLRiyDRgSDQutC70LDRgdGB0LDQvNC4IERPTVxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIERvbUNsYXNzIHtcclxuICAgIHB1YmxpYyBlbHQ6IERvbUVsZW1lbnQ7XHJcblxyXG4gICAgY29uc3RydWN0b3IoXHJcbiAgICAgICAgQEluamVjdChET0NVTUVOVCkgcHVibGljIGRvY3VtZW50OiBEb2N1bWVudCxcclxuICAgICkge1xyXG4gICAgICAgIHRoaXMuZWx0ID0gbmV3IERvbUVsZW1lbnQodGhpcy5kb2N1bWVudClcclxuICAgIH1cclxuXHJcbiAgICAvL3JlZ2lvbiDQo9C/0YDQsNCy0LvQtdC90LjQtSDQutC70LDRgdGB0LDQvNC4XHJcbiAgICAvKipcclxuICAgICAqINCf0YDQvtCy0LXRgNGP0LXRgiDQvdCw0LvQuNGH0LjQtSDQutC70LDRgdGB0LAg0YMg0Y3Qu9C10LzQtdC90YLQsFxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnQgLSDQrdC70LXQvNC10L3RglxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzTmFtZSAtINCa0LvQsNGB0YFcclxuICAgICAqXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSwg0LXRgdC70Lgg0LrQu9Cw0YHRgSDQv9GA0LjRgdGD0YLRgdGC0LLRg9C10YJcclxuICAgICAqL1xyXG4gICAgaGFzQ2xhc3MoZWxlbWVudDogSFRNTEVsZW1lbnQsIGNsYXNzTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuICEhKGNsYXNzTmFtZSAmJiBlbGVtZW50Py5jbGFzc0xpc3QuY29udGFpbnMoY2xhc3NOYW1lKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDQlNC+0LHQsNCy0LvRj9C10YIg0LrQu9Cw0YHRgSDRjdC70LXQvNC10L3RgtGDXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudCAtINCt0LvQtdC80LXQvdGCXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NOYW1lIC0g0JrQu9Cw0YHRgVxyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlLCDQtdGB0LvQuCDQutC70LDRgdGBINC00L7QsdCw0LLQuNC70LhcclxuICAgICAqL1xyXG4gICAgYWRkQ2xhc3MoZWxlbWVudDogSFRNTEVsZW1lbnQgfCBudWxsLCBjbGFzc05hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGlmIChjbGFzc05hbWUgJiYgZWxlbWVudCAmJiAnY2xhc3NMaXN0JyBpbiBlbGVtZW50KSB7XHJcbiAgICAgICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZChjbGFzc05hbWUpO1xyXG5cclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDQnNCw0YHRgdC+0LLQvtC1INC00L7QsdCw0LLQu9C10L3QuNC1IENTUy3QutC70LDRgdGB0L7QslxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnQgLSDQrdC70LXQvNC10L3RglxyXG4gICAgICogQHBhcmFtIGNsYXNzTmFtZXMgLSDQnNCw0YHRgdC40LIg0L3QsNC30LLQsNC90LjQuSBDU1Mt0LrQu9Cw0YHRgdC+0LIg0LTQu9GPINC00L7QsdCw0LLQu9C10L3QuNGPXHJcbiAgICAgKi9cclxuICAgIGFkZENsYXNzZXMoZWxlbWVudDogSFRNTEVsZW1lbnQgfCBudWxsLCBjbGFzc05hbWVzOiBzdHJpbmdbXSk6IHZvaWQge1xyXG4gICAgICAgIGlmICghZWxlbWVudCB8fCAhY2xhc3NOYW1lcyB8fCBjbGFzc05hbWVzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjbGFzc05hbWVzLmZvckVhY2goY2xhc3NOYW1lID0+IHtcclxuICAgICAgICAgICAgaWYgKGNsYXNzTmFtZSAmJiBjbGFzc05hbWUudHJpbSgpICE9PSAnJykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDbGFzcyhlbGVtZW50LCBjbGFzc05hbWUudHJpbSgpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICog0KHQvtC30LTQsNC10YIgQ1NTLdC60LvQsNGB0YHRiyDQtNC70Y8gbWFyZ2luINC4IHBhZGRpbmcg0L3QsCDQvtGB0L3QvtCy0LUg0L/QtdGA0LXQvNC10L3QvdGL0YUgLS1ldm97bn0uXHJcbiAgICAgKiDQmtC70LDRgdGB0Ysg0LPQtdC90LXRgNC40YDRg9GO0YLRgdGPINC00LvRjyDQstGB0LXRhSDQvdCw0L/RgNCw0LLQu9C10L3QuNC5ICh0b3AsIHJpZ2h0LCBib3R0b20sIGxlZnQpLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBlbGVtZW50UmVmIC0g0K3Qu9C10LzQtdC90YIg0LTQu9GPINC60L7RgtC+0YDQvtCz0L4g0LHRg9C00YPRgiDRgdC+0LfQtNCw0LLQsNGC0YzRgdGPINC60LvQsNGB0YHRiy5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyW119IGFyclZhcnMgLSDQl9C90LDRh9C10L3QuNGPINC00LvRjyDQs9C10L3QtdGA0LDRhtC40Lgg0LrQu9Cw0YHRgdC+0LIuXHJcbiAgICAgKlxyXG4gICAgICovXHJcbiAgICBhZGRDbGFzc01hcmdpblBhZGRpbmcoZWxlbWVudFJlZjogRWxlbWVudFJlZjxIVE1MRWxlbWVudD4sIGFyclZhcnM6IG51bWJlcltdID0gW10pOiB2b2lkIHtcclxuICAgICAgICBjb25zdCByb290ID0gdGhpcy5lbHQuZWxlbWVudEdldFBhcmVudChlbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQpO1xyXG5cclxuICAgICAgICBpZiAoIXJvb3QpIHtcclxuICAgICAgICAgICAgY29uc29sZS5lcnJvcignUm9vdCBlbGVtZW50IG5vdCBmb3VuZCcpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBwcm9wZXJ0aWVzID0gWydtJywgJ3AnXTsgLy8gbWFyZ2luLCBwYWRkaW5nXHJcbiAgICAgICAgY29uc3QgZGlyZWN0aW9ucyA9IFsndCcsICdyJywgJ2InLCAnbCddOyAvLyB0b3AsIHJpZ2h0LCBib3R0b20sIGxlZnRcclxuICAgICAgICBsZXQgc3R5bGUgPSB0aGlzLmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3N0eWxlW2RhdGEtZHluYW1pYy1zdHlsZV0nKTtcclxuXHJcbiAgICAgICAgaWYgKCFzdHlsZSkge1xyXG4gICAgICAgICAgICBzdHlsZSA9IHRoaXMuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcclxuICAgICAgICAgICAgc3R5bGUuc2V0QXR0cmlidXRlKCdkYXRhLWR5bmFtaWMtc3R5bGUnLCAnJyk7XHJcbiAgICAgICAgICAgIHJvb3QuYXBwZW5kQ2hpbGQoc3R5bGUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IGNzc0NvbnRlbnQgPSAnJztcclxuXHJcbiAgICAgICAgLy8g0JTQvtCx0LDQstC70Y/QtdC8INC60LvQsNGB0YHRiyDQtNC70Y8gYXJyVmFycyAo0LXRgdC70Lgg0LzQsNGB0YHQuNCyINC90LUg0L/Rg9GB0YLQvtC5KVxyXG4gICAgICAgIGlmIChhcnJWYXJzICYmIGFyclZhcnMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICBhcnJWYXJzLmZvckVhY2godmFsdWUgPT4ge1xyXG4gICAgICAgICAgICAgICAgcHJvcGVydGllcy5mb3JFYWNoKHByb3AgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbnMuZm9yRWFjaChkaXIgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjbGFzc05hbWUgPSBgLmV2by0ke3Byb3B9JHtkaXJ9LSR7dmFsdWV9YDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3NzUHJvcGVydHkgPSBwcm9wID09PSAnbScgPyAnbWFyZ2luJyA6ICdwYWRkaW5nJztcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3NzRGlyZWN0aW9uID0gdGhpcy5fZ2V0Q3NzRGlyZWN0aW9uKGRpcik7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjc3NDb250ZW50ICs9IGAke2NsYXNzTmFtZX0geyAke2Nzc1Byb3BlcnR5fS0ke2Nzc0RpcmVjdGlvbn06IHZhcigtLWV2byR7dmFsdWV9KTsgfVxcbmA7XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBzdHlsZS50ZXh0Q29udGVudCA9IGNzc0NvbnRlbnQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDQo9C00LDQu9C10L3QuNC1INCy0YHQtdGFINC60LvQsNGB0YHQvtCyINGB0L7Qt9C00LDQvdC90YvRhSDQsiBhZGRDbGFzc01hcmdpblBhZGRpbmcgKDxzdHlsZSBkYXRhLWR5bmFtaWMtc3R5bGU9XCJcIj4pXHJcbiAgICAgKiAgQHNlZSB7QGxpbmsgYWRkQ2xhc3NNYXJnaW5QYWRkaW5nfSAtINCh0L7Qt9C00LDQtdGCIENTUy3QutC70LDRgdGB0Ysg0LTQu9GPIG1hcmdpbiDQuCBwYWRkaW5nINC90LAg0L7RgdC90L7QstC1INC/0LXRgNC10LzQtdC90L3Ri9GFIC0tZXZve259LlxyXG4gICAgICovXHJcbiAgICBkZWxldGVDbGFzc01hcmdpblBhZGRpbmcoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdzdHlsZVtkYXRhLWR5bmFtaWMtc3R5bGVdJyk/LnJlbW92ZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICog0KPQtNCw0LvRj9C10YIg0LrQu9Cw0YHRgSDRgyDRjdC70LXQvNC10L3RgtCwXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudCAtINCt0LvQtdC80LXQvdGCXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NOYW1lIC0g0JrQu9Cw0YHRgVxyXG4gICAgICpcclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlLCDQtdGB0LvQuCDQutC70LDRgdGBINCx0YvQuyDRg9C00LDQu9C10L1cclxuICAgICAqL1xyXG4gICAgcmVtb3ZlQ2xhc3MoZWxlbWVudDogSFRNTEVsZW1lbnQgfCBudWxsLCBjbGFzc05hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGlmIChjbGFzc05hbWUgJiYgZWxlbWVudCAmJiAnY2xhc3NMaXN0JyBpbiBlbGVtZW50KSB7XHJcbiAgICAgICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShjbGFzc05hbWUpO1xyXG5cclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDQn9C10YDQtdC60LvRjtGH0LDQtdGCIENTUy3QutC70LDRgdGBINGDINC60L7RgNC90LXQstC+0LPQviDRjdC70LXQvNC10L3RgtCwXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudCAtINCt0LvQtdC80LXQvdGCXHJcbiAgICAgKiBAcGFyYW0gY2xhc3NOYW1lIC0g0J3QsNC30LLQsNC90LjQtSBDU1Mt0LrQu9Cw0YHRgdCwINC00LvRjyDQv9C10YDQtdC60LvRjtGH0LXQvdC40Y9cclxuICAgICAqIEBwYXJhbSBmb3JjZSAtINCf0YDQuNC90YPQtNC40YLQtdC70YzQvdC+INGD0YHRgtCw0L3QvtCy0LjRgtGMINC40LvQuCDRg9C00LDQu9C40YLRjCDQutC70LDRgdGBICh0cnVlIC0g0LTQvtCx0LDQstC40YLRjCwgZmFsc2UgLSDRg9C00LDQu9C40YLRjClcclxuICAgICAqL1xyXG4gICAgdG9nZ2xlQ2xhc3MoZWxlbWVudDogSFRNTEVsZW1lbnQgfCBudWxsLCBjbGFzc05hbWU6IHN0cmluZywgZm9yY2U/OiBib29sZWFuKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKCFlbGVtZW50IHx8ICFjbGFzc05hbWUpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgdHJpbW1lZENsYXNzTmFtZSA9IGNsYXNzTmFtZS50cmltKCk7XHJcblxyXG4gICAgICAgIGlmIChmb3JjZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIGlmIChmb3JjZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDbGFzcyhlbGVtZW50LCB0cmltbWVkQ2xhc3NOYW1lKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlQ2xhc3MoZWxlbWVudCwgdHJpbW1lZENsYXNzTmFtZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAvLyDQn9C10YDQtdC60LvRjtGH0LDQtdC8INC90LAg0L7RgdC90L7QstC1INGC0LXQutGD0YnQtdCz0L4g0YHQvtGB0YLQvtGP0L3QuNGPXHJcbiAgICAgICAgICAgIGlmICh0aGlzLmhhc0NsYXNzKGVsZW1lbnQsIHRyaW1tZWRDbGFzc05hbWUpKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUNsYXNzKGVsZW1lbnQsIHRyaW1tZWRDbGFzc05hbWUpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5hZGRDbGFzcyhlbGVtZW50LCB0cmltbWVkQ2xhc3NOYW1lKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqINCS0L7Qt9Cy0YDQsNGJ0LDQtdGCINC80LDRgdGB0LjQsiDQstGB0LXRhSBDU1Mt0LrQu9Cw0YHRgdC+0LIg0LrQvtGA0L3QtdCy0L7Qs9C+INGN0LvQtdC80LXQvdGC0LBcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50IC0g0K3Qu9C10LzQtdC90YJcclxuICAgICAqXHJcbiAgICAgKiBAcmV0dXJucyDQnNCw0YHRgdC40LIg0L3QsNC30LLQsNC90LjQuSBDU1Mt0LrQu9Cw0YHRgdC+0LJcclxuICAgICAqL1xyXG4gICAgZ2V0Q2xhc3NlcyhlbGVtZW50OiBIVE1MRWxlbWVudCB8IG51bGwpOiBzdHJpbmdbXSB7XHJcbiAgICAgICAgaWYgKGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgLy8g0J/QvtC70YPRh9Cw0LXQvCDQsNC60YLRg9Cw0LvRjNC90YvQtSDQutC70LDRgdGB0Ysg0YEg0Y3Qu9C10LzQtdC90YLQsFxyXG4gICAgICAgICAgICByZXR1cm4gQXJyYXkuZnJvbShlbGVtZW50LmNsYXNzTGlzdCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gW107XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDQo9C00LDQu9GP0LXRgiDQstGB0LUgQ1NTLdC60LvQsNGB0YHRiyDRgyDQutC+0YDQvdC10LLQvtCz0L4g0Y3Qu9C10LzQtdC90YLQsCDQuCDQvtGH0LjRidCw0LXRgiDQutGN0YhcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50IC0g0K3Qu9C10LzQtdC90YJcclxuICAgICAqL1xyXG4gICAgY2xlYXJDbGFzc2VzKGVsZW1lbnQ6IEhUTUxFbGVtZW50IHwgbnVsbCk6IHZvaWQge1xyXG4gICAgICAgIC8vINCj0LTQsNC70Y/QtdC8INCy0YHQtSDQutC70LDRgdGB0Ysg0YEg0Y3Qu9C10LzQtdC90YLQsFxyXG4gICAgICAgIGlmIChlbGVtZW50KSB7XHJcbiAgICAgICAgICAgIGVsZW1lbnQuY2xhc3NOYW1lID0gJyc7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vZW5kcmVnaW9uXHJcblxyXG4gICAgLy9yZWdpb24g0J/RgNC40LLQsNGC0L3Ri9C1INC80LXRgtC+0LTRi1xyXG5cclxuICAgIC8qKlxyXG4gICAgICog0J/RgNC10L7QsdGA0LDQt9GD0LXRgiDRgdC+0LrRgNCw0YnQtdC90L3QvtC1INC90LDQv9GA0LDQstC70LXQvdC40LUgKHQsIHIsIGIsIGwpINCyINC/0L7Qu9C90L7QtSDQvdCw0LfQstCw0L3QuNC1IENTUy3RgdCy0L7QudGB0YLQstCwLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBkaXIgLSDQodC+0LrRgNCw0YnQtdC90L3QvtC1INC90LDQv9GA0LDQstC70LXQvdC40LUgKHQsIHIsIGIsIGwpLlxyXG4gICAgICogQHJldHVybnMge3N0cmluZ30g0J/QvtC70L3QvtC1INC90LDQt9Cy0LDQvdC40LUg0L3QsNC/0YDQsNCy0LvQtdC90LjRjyAodG9wLCByaWdodCwgYm90dG9tLCBsZWZ0KS5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBfZ2V0Q3NzRGlyZWN0aW9uKGRpcjogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgICAgICBzd2l0Y2ggKGRpcikge1xyXG4gICAgICAgICAgICBjYXNlICd0JzpcclxuICAgICAgICAgICAgICAgIHJldHVybiAndG9wJztcclxuICAgICAgICAgICAgY2FzZSAncic6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJ3JpZ2h0JztcclxuICAgICAgICAgICAgY2FzZSAnYic6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2JvdHRvbSc7XHJcbiAgICAgICAgICAgIGNhc2UgJ2wnOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuICdsZWZ0JztcclxuICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgIHJldHVybiAnJztcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy9lbmRyZWdpb25cclxufVxyXG4iXX0=
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { __decorate, __param } from "tslib";
|
|
2
|
+
import { DOCUMENT } from '@angular/common';
|
|
3
|
+
import { Inject } from '@angular/core';
|
|
4
|
+
/**
|
|
5
|
+
* Предоставляет методы для манипуляции DOM элементами
|
|
6
|
+
*
|
|
7
|
+
* Класс включает функционал для:
|
|
8
|
+
* - Создания элементов
|
|
9
|
+
* - Добавления и удаления элементов из DOM
|
|
10
|
+
* - Поиска элементов с повторными попытками
|
|
11
|
+
* - Навигации по DOM дереву
|
|
12
|
+
* - Работы с data-атрибутами
|
|
13
|
+
*/
|
|
14
|
+
let DomElement = class DomElement {
|
|
15
|
+
constructor(document) {
|
|
16
|
+
this.document = document;
|
|
17
|
+
this._countGetElement = 0;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Создает новый DOM элемент с указанным тегом и CSS классом
|
|
21
|
+
*
|
|
22
|
+
* @param tagName - HTML тег создаваемого элемента (div, span, button и т.д.)
|
|
23
|
+
* @param className - CSS класс для элемента (опционально)
|
|
24
|
+
* @returns Новый DOM элемент
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* const div = worker.createElement('div', 'container');
|
|
28
|
+
* const span = worker.createElement('span');
|
|
29
|
+
*/
|
|
30
|
+
createElement(tagName, className) {
|
|
31
|
+
const element = this.document.createElement(tagName);
|
|
32
|
+
if (className) {
|
|
33
|
+
element.className = className;
|
|
34
|
+
}
|
|
35
|
+
return element;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Создает и добавляет новый HTML элемент в DOM
|
|
39
|
+
*
|
|
40
|
+
* @param parentElement - Родительский элемент, к которому будет добавлен новый
|
|
41
|
+
* @param newElement - HTML тег создаваемого элемента
|
|
42
|
+
* @param typeAppend - Способ добавления ('appendChild' или 'insertBefore')
|
|
43
|
+
* @param strInnerHTML - Внутреннее HTML содержимое (опционально)
|
|
44
|
+
* @param dataId - Значение для атрибута data-id (опционально)
|
|
45
|
+
* @param eventName - Тип события для добавления слушателя
|
|
46
|
+
* @param fn - Функция-обработчик события (опционально)
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* worker.elementCreate(
|
|
50
|
+
* this.document.body,
|
|
51
|
+
* 'button',
|
|
52
|
+
* 'appendChild',
|
|
53
|
+
* 'Click me',
|
|
54
|
+
* 123,
|
|
55
|
+
* 'click',
|
|
56
|
+
* () => console.log('Clicked')
|
|
57
|
+
* );
|
|
58
|
+
*/
|
|
59
|
+
elementCreate(parentElement, newElement, typeAppend, strInnerHTML = '', dataId = '', eventName, fn = null) {
|
|
60
|
+
if (!parentElement || !newElement) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const el$ = this.document.createElement(newElement);
|
|
64
|
+
if (dataId !== null) {
|
|
65
|
+
el$.setAttribute('data-id', String(dataId));
|
|
66
|
+
}
|
|
67
|
+
if (strInnerHTML) {
|
|
68
|
+
el$.innerHTML = strInnerHTML;
|
|
69
|
+
}
|
|
70
|
+
this.elementAdd(parentElement, typeAppend, dataId, eventName, fn, el$);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Добавляет существующий HTML элемент в DOM
|
|
74
|
+
*
|
|
75
|
+
* @param parentElement - Родительский элемент
|
|
76
|
+
* @param typeAppend - Способ добавления ('appendChild' или 'insertBefore')
|
|
77
|
+
* @param dataId - Идентификатор для атрибута data-id
|
|
78
|
+
* @param eventName - Тип события для слушателя
|
|
79
|
+
* @param fn - Функция-обработчик события
|
|
80
|
+
* @param el$ - Добавляемый DOM элемент
|
|
81
|
+
*
|
|
82
|
+
* @remarks
|
|
83
|
+
* Если typeAppend равен 'insertBefore', элемент добавляется в начало родителя.
|
|
84
|
+
* В противном случае элемент добавляется в конец.
|
|
85
|
+
*/
|
|
86
|
+
elementAdd(parentElement, typeAppend, dataId, eventName, fn, el$) {
|
|
87
|
+
if ('firstChild' in parentElement) {
|
|
88
|
+
if (typeAppend === 'insertBefore') {
|
|
89
|
+
parentElement.insertBefore(el$, parentElement.firstChild);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
parentElement.appendChild(el$);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
parentElement.appendChild(el$);
|
|
97
|
+
}
|
|
98
|
+
if (fn) {
|
|
99
|
+
el$.addEventListener(eventName, event => {
|
|
100
|
+
fn.call(null, event, null, el$, dataId);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Удаляет HTML элемент из DOM
|
|
106
|
+
*
|
|
107
|
+
* @param parentElement - Родительский элемент, содержащий удаляемый элемент
|
|
108
|
+
* @param el$ - Удаляемый DOM элемент
|
|
109
|
+
*
|
|
110
|
+
* @remarks
|
|
111
|
+
* Метод безопасно завершается, если parentElement или el$ отсутствуют
|
|
112
|
+
*/
|
|
113
|
+
elementRemove(parentElement, el$) {
|
|
114
|
+
if (parentElement && el$) {
|
|
115
|
+
parentElement.removeChild(el$);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Асинхронно получает HTML элемент с повторными попытками
|
|
120
|
+
*
|
|
121
|
+
* @param identifier - Селектор для поиска элемента
|
|
122
|
+
* @param selector - Метод поиска ('querySelector' или 'querySelectorAll')
|
|
123
|
+
* @param node - DOM узел для поиска (по умолчанию this.document)
|
|
124
|
+
* @param time - Задержка между попытками в мс (по умолчанию 300)
|
|
125
|
+
* @param max - Максимальное количество попыток (по умолчанию 10)
|
|
126
|
+
* @returns Промис с найденным DOM элементом
|
|
127
|
+
*
|
|
128
|
+
* @remarks
|
|
129
|
+
* Метод полезен для ожидания появления динамически создаваемых элементов
|
|
130
|
+
*/
|
|
131
|
+
async elementGet(identifier, selector = 'querySelector', node = this.document, time = 300, max = 10) {
|
|
132
|
+
let result = await this._getElementResult(identifier, selector, node, time);
|
|
133
|
+
if ((!result || (result instanceof NodeList && result.length < 1)) && this._countGetElement < max) {
|
|
134
|
+
this._countGetElement++;
|
|
135
|
+
result = await this.elementGet(identifier, selector, node, time, max);
|
|
136
|
+
}
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Находит элементы по data-атрибуту или его значению
|
|
141
|
+
*
|
|
142
|
+
* @param elementToSelect - Название data-атрибута (например, 'data-id')
|
|
143
|
+
* @param dataValue - Значение атрибута для фильтрации (опционально)
|
|
144
|
+
* @returns Массив найденных элементов
|
|
145
|
+
* @throws {Error} Если elementToSelect не указан
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* // Найти все элементы с data-id
|
|
149
|
+
* const items = worker.getElementByDataAttribute('data-id');
|
|
150
|
+
*
|
|
151
|
+
* // Найти элемент с конкретным значением
|
|
152
|
+
* const item = worker.getElementByDataAttribute('data-id', '123');
|
|
153
|
+
*/
|
|
154
|
+
getElementByDataAttribute(elementToSelect, dataValue = null) {
|
|
155
|
+
if (!elementToSelect) {
|
|
156
|
+
throw new Error('elementToSelect is required for getElementByDataAttribute');
|
|
157
|
+
}
|
|
158
|
+
const selector = dataValue ? `[${elementToSelect}='${dataValue}']` : `[${elementToSelect}]`;
|
|
159
|
+
const elements = this.document.querySelectorAll(selector);
|
|
160
|
+
return Array.from(elements);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Внутренний метод для получения элемента с задержкой
|
|
164
|
+
*
|
|
165
|
+
* @param identifier - Селектор элемента
|
|
166
|
+
* @param selector - Метод поиска
|
|
167
|
+
* @param node - Корневой узел
|
|
168
|
+
* @param time - Время задержки в мс
|
|
169
|
+
* @returns Промис с результатом поиска
|
|
170
|
+
* @private
|
|
171
|
+
*/
|
|
172
|
+
async _getElementResult(identifier, selector, node, time) {
|
|
173
|
+
return this._setDelay(time)
|
|
174
|
+
.then(_ => {
|
|
175
|
+
if (!node) {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
// Используем type assertion для вызова метода
|
|
179
|
+
const result = node[selector](identifier);
|
|
180
|
+
return result || null;
|
|
181
|
+
})
|
|
182
|
+
.catch(error => console.log('Ошибка в _getElementResult', error));
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Создает Promise с задержкой
|
|
186
|
+
*
|
|
187
|
+
* @param ms - Время задержки в миллисекундах
|
|
188
|
+
* @returns Promise, который разрешается через указанное время
|
|
189
|
+
* @private
|
|
190
|
+
*/
|
|
191
|
+
_setDelay(ms) {
|
|
192
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Возвращает размеры элемента и его положение относительно viewport
|
|
196
|
+
*
|
|
197
|
+
* @param element - Целевой DOM элемент
|
|
198
|
+
* @returns DOMRect объект с координатами (top, left, right, bottom) и размерами (width, height)
|
|
199
|
+
* @throws {Error} Если element не указан
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* const rect = worker.getCoordinates(buttonElement);
|
|
203
|
+
* console.log(rect.top, rect.left, rect.width);
|
|
204
|
+
*/
|
|
205
|
+
getCoordinates(element) {
|
|
206
|
+
if (!element) {
|
|
207
|
+
throw new Error('Element is required for getCoordinates');
|
|
208
|
+
}
|
|
209
|
+
return element.getBoundingClientRect();
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Возвращает родительский элемент указанного DOM узла
|
|
213
|
+
*
|
|
214
|
+
* @param el - DOM элемент или NodeList
|
|
215
|
+
* @returns Родительский элемент или null, если родителя нет
|
|
216
|
+
*/
|
|
217
|
+
elementGetParent(el) {
|
|
218
|
+
if (el && 'parentNode' in el) {
|
|
219
|
+
return el.parentNode;
|
|
220
|
+
}
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Возвращает все соседние элементы (включая сам элемент)
|
|
225
|
+
*
|
|
226
|
+
* @param el - Исходный DOM элемент
|
|
227
|
+
* @returns Массив всех элементов в текущей ветке DOM дерева
|
|
228
|
+
*
|
|
229
|
+
* @remarks
|
|
230
|
+
* Метод собирает все элементы на одном уровне вложенности
|
|
231
|
+
*/
|
|
232
|
+
elementsGetSiblingAll(el) {
|
|
233
|
+
if (el && 'parentNode' in el) {
|
|
234
|
+
const parent = el.parentNode;
|
|
235
|
+
const firstElement = parent.firstChild;
|
|
236
|
+
return this.elementGetSiblingNext(firstElement);
|
|
237
|
+
}
|
|
238
|
+
return [];
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Возвращает все следующие соседние элементы (nextElementSibling)
|
|
242
|
+
*
|
|
243
|
+
* @param el - Исходный DOM элемент
|
|
244
|
+
* @returns Массив элементов, начиная с указанного и включая все следующие
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* const nextElements = worker.elementGetSiblingNext(currentElement);
|
|
248
|
+
* // Возвращает [currentElement, nextElement, nextNextElement, ...]
|
|
249
|
+
*/
|
|
250
|
+
elementGetSiblingNext(el) {
|
|
251
|
+
const result = [];
|
|
252
|
+
while (el) {
|
|
253
|
+
if ('nextElementSibling' in el) {
|
|
254
|
+
result.push(el);
|
|
255
|
+
el = el.nextElementSibling;
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return result;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Возвращает все предыдущие соседние элементы (previousSibling)
|
|
265
|
+
*
|
|
266
|
+
* @param el - Исходный DOM элемент
|
|
267
|
+
* @returns Массив предыдущих элементов
|
|
268
|
+
*
|
|
269
|
+
* @remarks
|
|
270
|
+
* Возвращает все элементы, включая указанный, в обратном порядке
|
|
271
|
+
*/
|
|
272
|
+
elementGetSiblingPrevious(el) {
|
|
273
|
+
const result = [];
|
|
274
|
+
let current = el;
|
|
275
|
+
while (current) {
|
|
276
|
+
result.push(current);
|
|
277
|
+
current = current.previousSibling;
|
|
278
|
+
}
|
|
279
|
+
return result;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Возвращает все прямые дочерние элементы указанного родителя
|
|
283
|
+
*
|
|
284
|
+
* @param el - Родительский DOM элемент
|
|
285
|
+
* @returns Массив дочерних элементов
|
|
286
|
+
*
|
|
287
|
+
* @example
|
|
288
|
+
* const children = worker.elementGetChildren(parentElement);
|
|
289
|
+
* children.forEach(child => console.log(child.tagName));
|
|
290
|
+
*/
|
|
291
|
+
elementGetChildren(el) {
|
|
292
|
+
return Array.from(el.children);
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
DomElement = __decorate([
|
|
296
|
+
__param(0, Inject(DOCUMENT))
|
|
297
|
+
], DomElement);
|
|
298
|
+
export { DomElement };
|
|
299
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9tLWVsZW1lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90b29sLWRvbS1hbmcxNS9zcmMvbGliL2RvbS9zb3VyY2UvZG9tLWVsZW1lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBS3JDOzs7Ozs7Ozs7R0FTRztBQUNJLElBQU0sVUFBVSxHQUFoQixNQUFNLFVBQVU7SUFJbkIsWUFBcUMsUUFBa0I7UUFBbEIsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQUYvQyxxQkFBZ0IsR0FBRyxDQUFDLENBQUM7SUFHN0IsQ0FBQztJQUVEOzs7Ozs7Ozs7O09BVUc7SUFDSCxhQUFhLENBQUMsT0FBZSxFQUFFLFNBQWtCO1FBQzdDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3JELElBQUksU0FBUyxFQUFFO1lBQ1gsT0FBTyxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7U0FDakM7UUFDRCxPQUFPLE9BQU8sQ0FBQztJQUNuQixDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQXFCRztJQUNILGFBQWEsQ0FDVCxhQUEwQixFQUMxQixVQUFrQixFQUNsQixVQUF1QixFQUN2QixlQUF1QixFQUFFLEVBQ3pCLFNBQTBCLEVBQUUsRUFDNUIsU0FBcUIsRUFDckIsS0FBc0QsSUFBSTtRQUUxRCxJQUFJLENBQUMsYUFBYSxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQy9CLE9BQU87U0FDVjtRQUVELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRXBELElBQUksTUFBTSxLQUFLLElBQUksRUFBRTtZQUNqQixHQUFHLENBQUMs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bnQiOlsiaW1wb3J0IHtET0NVTUVOVH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHtJbmplY3R9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuaW1wb3J0IHtUQWxsRXZlbnRzLCBUU2VsZWN0b3IsIFRUeXBlQXBwZW5kfSBmcm9tICcuL2RvbS5pbnRlcmZhY2UnO1xyXG5cclxuXHJcbi8qKlxyXG4gKiDQn9GA0LXQtNC+0YHRgtCw0LLQu9GP0LXRgiDQvNC10YLQvtC00Ysg0LTQu9GPINC80LDQvdC40L/Rg9C70Y/RhtC40LggRE9NINGN0LvQtdC80LXQvdGC0LDQvNC4XHJcbiAqXHJcbiAqINCa0LvQsNGB0YEg0LLQutC70Y7Rh9Cw0LXRgiDRhNGD0L3QutGG0LjQvtC90LDQuyDQtNC70Y86XHJcbiAqIC0g0KHQvtC30LTQsNC90LjRjyDRjdC70LXQvNC10L3RgtC+0LJcclxuICogLSDQlNC+0LHQsNCy0LvQtdC90LjRjyDQuCDRg9C00LDQu9C10L3QuNGPINGN0LvQtdC80LXQvdGC0L7QsiDQuNC3IERPTVxyXG4gKiAtINCf0L7QuNGB0LrQsCDRjdC70LXQvNC10L3RgtC+0LIg0YEg0L/QvtCy0YLQvtGA0L3Ri9C80Lgg0L/QvtC/0YvRgtC60LDQvNC4XHJcbiAqIC0g0J3QsNCy0LjQs9Cw0YbQuNC4INC/0L4gRE9NINC00LXRgNC10LLRg1xyXG4gKiAtINCg0LDQsdC+0YLRiyDRgSBkYXRhLdCw0YLRgNC40LHRg9GC0LDQvNC4XHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgRG9tRWxlbWVudCB7XHJcblxyXG4gICAgcHJpdmF0ZSBfY291bnRHZXRFbGVtZW50ID0gMDtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihASW5qZWN0KERPQ1VNRU5UKSBwdWJsaWMgZG9jdW1lbnQ6IERvY3VtZW50KSB7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDQodC+0LfQtNCw0LXRgiDQvdC+0LLRi9C5IERPTSDRjdC70LXQvNC10L3RgiDRgSDRg9C60LDQt9Cw0L3QvdGL0Lwg0YLQtdCz0L7QvCDQuCBDU1Mg0LrQu9Cw0YHRgdC+0LxcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gdGFnTmFtZSAtIEhUTUwg0YLQtdCzINGB0L7Qt9C00LDQstCw0LXQvNC+0LPQviDRjdC70LXQvNC10L3RgtCwIChkaXYsIHNwYW4sIGJ1dHRvbiDQuCDRgi7QtC4pXHJcbiAgICAgKiBAcGFyYW0gY2xhc3NOYW1lIC0gQ1NTINC60LvQsNGB0YEg0LTQu9GPINGN0LvQtdC80LXQvdGC0LAgKNC+0L/RhtC40L7QvdCw0LvRjNC90L4pXHJcbiAgICAgKiBAcmV0dXJucyDQndC+0LLRi9C5IERPTSDRjdC70LXQvNC10L3RglxyXG4gICAgICpcclxuICAgICAqIEBleGFtcGxlXHJcbiAgICAgKiBjb25zdCBkaXYgPSB3b3JrZXIuY3JlYXRlRWxlbWVudCgnZGl2JywgJ2NvbnRhaW5lcicpO1xyXG4gICAgICogY29uc3Qgc3BhbiA9IHdvcmtlci5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XHJcbiAgICAgKi9cclxuICAgIGNyZWF0ZUVsZW1lbnQodGFnTmFtZTogc3RyaW5nLCBjbGFzc05hbWU/OiBzdHJpbmcpOiBIVE1MRWxlbWVudCB7XHJcbiAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKTtcclxuICAgICAgICBpZiAoY2xhc3NOYW1lKSB7XHJcbiAgICAgICAgICAgIGVsZW1lbnQuY2xhc3NOYW1lID0gY2xhc3NOYW1lO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gZWxlbWVudDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqINCh0L7Qt9C00LDQtdGCINC4INC00L7QsdCw0LLQu9GP0LXRgiDQvdC+0LLRi9C5IEhUTUwg0Y3Qu9C10LzQtdC90YIg0LIgRE9NXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHBhcmVudEVsZW1lbnQgLSDQoNC+0LTQuNGC0LXQu9GM0YHQutC40Lkg0Y3Qu9C10LzQtdC90YIsINC6INC60L7RgtC+0YDQvtC80YMg0LHRg9C00LXRgiDQtNC+0LHQsNCy0LvQtdC9INC90L7QstGL0LlcclxuICAgICAqIEBwYXJhbSBuZXdFbGVtZW50IC0gSFRNTCDRgtC10LMg0YHQvtC30LTQsNCy0LDQtdC80L7Qs9C+INGN0LvQtdC80LXQvdGC0LBcclxuICAgICAqIEBwYXJhbSB0eXBlQXBwZW5kIC0g0KHQv9C+0YHQvtCxINC00L7QsdCw0LLQu9C10L3QuNGPICgnYXBwZW5kQ2hpbGQnINC40LvQuCAnaW5zZXJ0QmVmb3JlJylcclxuICAgICAqIEBwYXJhbSBzdHJJbm5lckhUTUwgLSDQktC90YPRgtGA0LXQvdC90LXQtSBIVE1MINGB0L7QtNC10YDQttC40LzQvtC1ICjQvtC/0YbQuNC+0L3QsNC70YzQvdC+KVxyXG4gICAgICogQHBhcmFtIGRhdGFJZCAtINCX0L3QsNGH0LXQvdC40LUg0LTQu9GPINCw0YLRgNC40LHRg9GC0LAgZGF0YS1pZCAo0L7Qv9GG0LjQvtC90LDQu9GM0L3QvilcclxuICAgICAqIEBwYXJhbSBldmVudE5hbWUgLSDQotC40L8g0YHQvtCx0YvRgtC40Y8g0LTQu9GPINC00L7QsdCw0LLQu9C10L3QuNGPINGB0LvRg9GI0LDRgtC10LvRj1xyXG4gICAgICogQHBhcmFtIGZuIC0g0KTRg9C90LrRhtC40Y8t0L7QsdGA0LDQsdC+0YLRh9C40Log0YHQvtCx0YvRgtC40Y8gKNC+0L/RhtC40L7QvdCw0LvRjNC90L4pXHJcbiAgICAgKlxyXG4gICAgICogQGV4YW1wbGVcclxuICAgICAqIHdvcmtlci5lbGVtZW50Q3JlYXRlKFxyXG4gICAgICogICB0aGlzLmRvY3VtZW50LmJvZHksXHJcbiAgICAgKiAgICdidXR0b24nLFxyXG4gICAgICogICAnYXBwZW5kQ2hpbGQnLFxyXG4gICAgICogICAnQ2xpY2sgbWUnLFxyXG4gICAgICogICAxMjMsXHJcbiAgICAgKiAgICdjbGljaycsXHJcbiAgICAgKiAgICgpID0+IGNvbnNvbGUubG9nKCdDbGlja2VkJylcclxuICAgICAqICk7XHJcbiAgICAgKi9cclxuICAgIGVsZW1lbnRDcmVhdGUoXHJcbiAgICAgICAgcGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQsXHJcbiAgICAgICAgbmV3RWxlbWVudDogc3RyaW5nLFxyXG4gICAgICAgIHR5cGVBcHBlbmQ6IFRUeXBlQXBwZW5kLFxyXG4gICAgICAgIHN0cklubmVySFRNTDogc3RyaW5nID0gJycsXHJcbiAgICAgICAgZGF0YUlkOiBudW1iZXIgfCBzdHJpbmcgPSAnJyxcclxuICAgICAgICBldmVudE5hbWU6IFRBbGxFdmVudHMsXHJcbiAgICAgICAgZm46ICgoZXZlbnQ6IEV2ZW50LCAuLi5hcmdzOiBhbnlbXSkgPT4gdm9pZCkgfCBudWxsID0gbnVsbFxyXG4gICAgKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKCFwYXJlbnRFbGVtZW50IHx8ICFuZXdFbGVtZW50KSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGVsJCA9IHRoaXMuZG9jdW1lbnQuY3JlYXRlRWxlbWVudChuZXdFbGVtZW50KTtcclxuXHJcbiAgICAgICAgaWYgKGRhdGFJZCAhPT0gbnVsbCkge1xyXG4gICAgICAgICAgICBlbCQuc2V0QXR0cmlidXRlKCdkYXRhLWlkJywgU3RyaW5nKGRhdGFJZCkpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHN0cklubmVySFRNTCkge1xyXG4gICAgICAgICAgICBlbCQuaW5uZXJIVE1MID0gc3RySW5uZXJIVE1MO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5lbGVtZW50QWRkKHBhcmVudEVsZW1lbnQsIHR5cGVBcHBlbmQsIGRhdGFJZCwgZXZlbnROYW1lLCBmbiwgZWwkKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqINCU0L7QsdCw0LLQu9GP0LXRgiDRgdGD0YnQtdGB0YLQstGD0Y7RidC40LkgSFRNTCDRjdC70LXQvNC10L3RgiDQsiBET01cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gcGFyZW50RWxlbWVudCAtINCg0L7QtNC40YLQtdC70YzRgdC60LjQuSDRjdC70LXQvNC10L3RglxyXG4gICAgICogQHBhcmFtIHR5cGVBcHBlbmQgLSDQodC/0L7RgdC+0LEg0LTQvtCx0LDQstC70LXQvdC40Y8gKCdhcHBlbmRDaGlsZCcg0LjQu9C4ICdpbnNlcnRCZWZvcmUnKVxyXG4gICAgICogQHBhcmFtIGRhdGFJZCAtINCY0LTQtdC90YLQuNGE0LjQutCw0YLQvtGAINC00LvRjyDQsNGC0YDQuNCx0YPRgtCwIGRhdGEtaWRcclxuICAgICAqIEBwYXJhbSBldmVudE5hbWUgLSDQotC40L8g0YHQvtCx0YvRgtC40Y8g0LTQu9GPINGB0LvRg9GI0LDRgtC10LvRj1xyXG4gICAgICogQHBhcmFtIGZuIC0g0KTRg9C90LrRhtC40Y8t0L7QsdGA0LDQsdC+0YLRh9C40Log0YHQvtCx0YvRgtC40Y9cclxuICAgICAqIEBwYXJhbSBlbCQgLSDQlNC+0LHQsNCy0LvRj9C10LzRi9C5IERPTSDRjdC70LXQvNC10L3RglxyXG4gICAgICpcclxuICAgICAqIEByZW1hcmtzXHJcbiAgICAgKiDQldGB0LvQuCB0eXBlQXBwZW5kINGA0LDQstC10L0gJ2luc2VydEJlZm9yZScsINGN0LvQtdC80LXQvdGCINC00L7QsdCw0LLQu9GP0LXRgtGB0Y8g0LIg0L3QsNGH0LDQu9C+INGA0L7QtNC40YLQtdC70Y8uXHJcbiAgICAgKiDQkiDQv9GA0L7RgtC40LLQvdC+0Lwg0YHQu9GD0YfQsNC1INGN0LvQtdC80LXQvdGCINC00L7QsdCw0LLQu9GP0LXRgtGB0Y8g0LIg0LrQvtC90LXRhi5cclxuICAgICAqL1xyXG4gICAgZWxlbWVudEFkZChcclxuICAgICAgICBwYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCxcclxuICAgICAgICB0eXBlQXBwZW5kOiBUVHlwZUFwcGVuZCxcclxuICAgICAgICBkYXRhSWQ6IG51bWJlciB8IHN0cmluZyxcclxuICAgICAgICBldmVudE5hbWU6IFRBbGxFdmVudHMsXHJcbiAgICAgICAgZm46ICgoZXZlbnQ6IEV2ZW50LCAuLi5hcmdzOiBhbnlbXSkgPT4gdm9pZCkgfCBudWxsLFxyXG4gICAgICAgIGVsJDogSFRNTEVsZW1lbnRcclxuICAgICk6IHZvaWQge1xyXG4gICAgICAgIGlmICgnZmlyc3RDaGlsZCcgaW4gcGFyZW50RWxlbWVudCkge1xyXG4gICAgICAgICAgICBpZiAodHlwZUFwcGVuZCA9PT0gJ2luc2VydEJlZm9yZScpIHtcclxuICAgICAgICAgICAgICAgIChwYXJlbnRFbGVtZW50IGFzIE5vZGUpLmluc2VydEJlZm9yZShlbCQsIHBhcmVudEVsZW1lbnQuZmlyc3RDaGlsZCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAocGFyZW50RWxlbWVudCBhcyBOb2RlKS5hcHBlbmRDaGlsZChlbCQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgKHBhcmVudEVsZW1lbnQgYXMgTm9kZSkuYXBwZW5kQ2hpbGQoZWwkKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChmbikge1xyXG4gICAgICAgICAgICBlbCQuYWRkRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGV2ZW50ID0+IHtcclxuICAgICAgICAgICAgICAgIGZuLmNhbGwobnVsbCwgZXZlbnQsIG51bGwsIGVsJCwgZGF0YUlkKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICog0KPQtNCw0LvRj9C10YIgSFRNTCDRjdC70LXQvNC10L3RgiDQuNC3IERPTVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBwYXJlbnRFbGVtZW50IC0g0KDQvtC00LjRgtC10LvRjNGB0LrQuNC5INGN0LvQtdC80LXQvdGCLCDRgdC+0LTQtdGA0LbQsNGJ0LjQuSDRg9C00LDQu9GP0LXQvNGL0Lkg0Y3Qu9C10LzQtdC90YJcclxuICAgICAqIEBwYXJhbSBlbCQgLSDQo9C00LDQu9GP0LXQvNGL0LkgRE9NINGN0LvQtdC80LXQvdGCXHJcbiAgICAgKlxyXG4gICAgICogQHJlbWFya3NcclxuICAgICAqINCc0LXRgtC+0LQg0LHQtdC30L7Qv9Cw0YHQvdC+INC30LDQstC10YDRiNCw0LXRgtGB0Y8sINC10YHQu9C4IHBhcmVudEVsZW1lbnQg0LjQu9C4IGVsJCDQvtGC0YHRg9GC0YHRgtCy0YPRjtGCXHJcbiAgICAgKi9cclxuICAgIGVsZW1lbnRSZW1vdmUocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQsIGVsJDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcclxuICAgICAgICBpZiAocGFyZW50RWxlbWVudCAmJiBlbCQpIHtcclxuICAgICAgICAgICAgKHBhcmVudEVsZW1lbnQgYXMgTm9kZSkucmVtb3ZlQ2hpbGQoZWwkKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDQkNGB0LjQvdGF0YDQvtC90L3QviDQv9C+0LvRg9GH0LDQtdGCIEhUTUwg0Y3Qu9C10LzQtdC90YIg0YEg0L/QvtCy0YLQvtGA0L3Ri9C80Lgg0L/QvtC/0YvRgtC60LDQvNC4XHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIGlkZW50aWZpZXIgLSDQodC10LvQtdC60YLQvtGAINC00LvRjyDQv9C+0LjRgdC60LAg0Y3Qu9C10LzQtdC90YLQsFxyXG4gICAgICogQHBhcmFtIHNlbGVjdG9yIC0g0JzQtdGC0L7QtCDQv9C+0LjRgdC60LAgKCdxdWVyeVNlbGVjdG9yJyDQuNC70LggJ3F1ZXJ5U2VsZWN0b3JBbGwnKVxyXG4gICAgICogQHBhcmFtIG5vZGUgLSBET00g0YPQt9C10Lsg0LTQu9GPINC/0L7QuNGB0LrQsCAo0L/QviDRg9C80L7Qu9GH0LDQvdC40Y4gdGhpcy5kb2N1bWVudClcclxuICAgICAqIEBwYXJhbSB0aW1lIC0g0JfQsNC00LXRgNC20LrQsCDQvNC10LbQtNGDINC/0L7Qv9GL0YLQutCw0LzQuCDQsiDQvNGBICjQv9C+INGD0LzQvtC70YfQsNC90LjRjiAzMDApXHJcbiAgICAgKiBAcGFyYW0gbWF4IC0g0JzQsNC60YHQuNC80LDQu9GM0L3QvtC1INC60L7Qu9C40YfQtdGB0YLQstC+INC/0L7Qv9GL0YLQvtC6ICjQv9C+INGD0LzQvtC70YfQsNC90LjRjiAxMClcclxuICAgICAqIEByZXR1cm5zINCf0YDQvtC80LjRgSDRgSDQvdCw0LnQtNC10L3QvdGL0LwgRE9NINGN0LvQtdC80LXQvdGC0L7QvFxyXG4gICAgICpcclxuICAgICAqIEByZW1hcmtzXHJcbiAgICAgKiDQnNC10YLQvtC0INC/0L7Qu9C10LfQtdC9INC00LvRjyDQvtC20LjQtNCw0L3QuNGPINC/0L7Rj9Cy0LvQtdC90LjRjyDQtNC40L3QsNC80LjRh9C10YHQutC4INGB0L7Qt9C00LDQstCw0LXQvNGL0YUg0Y3Qu9C10LzQtdC90YLQvtCyXHJcbiAgICAgKi9cclxuICAgIGFzeW5jIGVsZW1lbnRHZXQoXHJcbiAgICAgICAgaWRlbnRpZmllcjogc3RyaW5nLFxyXG4gICAgICAgIHNlbGVjdG9yOiBUU2VsZWN0b3IgPSAncXVlcnlTZWxlY3RvcicsXHJcbiAgICAgICAgbm9kZTogRG9jdW1lbnQgfCBIVE1MRWxlbWVudCB8IG51bGwgPSB0aGlzLmRvY3VtZW50LFxyXG4gICAgICAgIHRpbWU6IG51bWJlciA9IDMwMCxcclxuICAgICAgICBtYXg6IG51bWJlciA9IDEwXHJcbiAgICApOiBQcm9taXNlPEhUTUxFbGVtZW50PiB7XHJcbiAgICAgICAgbGV0IHJlc3VsdCA9IGF3YWl0IHRoaXMuX2dldEVsZW1lbnRSZXN1bHQoaWRlbnRpZmllciwgc2VsZWN0b3IsIG5vZGUsIHRpbWUpO1xyXG5cclxuICAgICAgICBpZiAoKCFyZXN1bHQgfHwgKHJlc3VsdCBpbnN0YW5jZW9mIE5vZGVMaXN0ICYmIHJlc3VsdC5sZW5ndGggPCAxKSkgJiYgdGhpcy5fY291bnRHZXRFbGVtZW50IDwgbWF4KSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2NvdW50R2V0RWxlbWVudCsrO1xyXG4gICAgICAgICAgICByZXN1bHQgPSBhd2FpdCB0aGlzLmVsZW1lbnRHZXQoaWRlbnRpZmllciwgc2VsZWN0b3IsIG5vZGUsIHRpbWUsIG1heCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICog0J3QsNGF0L7QtNC40YIg0Y3Qu9C10LzQtdC90YLRiyDQv9C+IGRhdGEt0LDRgtGA0LjQsdGD0YLRgyDQuNC70Lgg0LXQs9C+INC30L3QsNGH0LXQvdC40Y5cclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gZWxlbWVudFRvU2VsZWN0IC0g0J3QsNC30LLQsNC90LjQtSBkYXRhLdCw0YLRgNC40LHRg9GC0LAgKNC90LDQv9GA0LjQvNC10YAsICdkYXRhLWlkJylcclxuICAgICAqIEBwYXJhbSBkYXRhVmFsdWUgLSDQl9C90LDRh9C10L3QuNC1INCw0YLRgNC40LHRg9GC0LAg0LTQu9GPINGE0LjQu9GM0YLRgNCw0YbQuNC4ICjQvtC/0YbQuNC+0L3QsNC70YzQvdC+KVxyXG4gICAgICogQHJldHVybnMg0JzQsNGB0YHQuNCyINC90LDQudC00LXQvdC90YvRhSDRjdC70LXQvNC10L3RgtC+0LJcclxuICAgICAqIEB0aHJvd3Mge0Vycm9yfSDQldGB0LvQuCBlbGVtZW50VG9TZWxlY3Qg0L3QtSDRg9C60LDQt9Cw0L1cclxuICAgICAqXHJcbiAgICAgKiBAZXhhbXBsZVxyXG4gICAgICogLy8g0J3QsNC50YLQuCDQstGB0LUg0Y3Qu9C10LzQtdC90YLRiyDRgSBkYXRhLWlkXHJcbiAgICAgKiBjb25zdCBpdGVtcyA9IHdvcmtlci5nZXRFbGVtZW50QnlEYXRhQXR0cmlidXRlKCdkYXRhLWlkJyk7XHJcbiAgICAgKlxyXG4gICAgICogLy8g0J3QsNC50YLQuCDRjdC70LXQvNC10L3RgiDRgSDQutC+0L3QutGA0LXRgtC90YvQvCDQt9C90LDRh9C10L3QuNC10LxcclxuICAgICAqIGNvbnN0IGl0ZW0gPSB3b3JrZXIuZ2V0RWxlbWVudEJ5RGF0YUF0dHJpYnV0ZSgnZGF0YS1pZCcsICcxMjMnKTtcclxuICAgICAqL1xyXG4gICAgZ2V0RWxlbWVudEJ5RGF0YUF0dHJpYnV0ZShlbGVtZW50VG9TZWxlY3Q6IHN0cmluZywgZGF0YVZhbHVlOiBzdHJpbmcgfCBudWxsID0gbnVsbCk6IEhUTUxFbGVtZW50W10ge1xyXG4gICAgICAgIGlmICghZWxlbWVudFRvU2VsZWN0KSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignZWxlbWVudFRvU2VsZWN0IGlzIHJlcXVpcmVkIGZvciBnZXRFbGVtZW50QnlEYXRhQXR0cmlidXRlJyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IHNlbGVjdG9yID0gZGF0YVZhbHVlID8gYFske2VsZW1lbnRUb1NlbGVjdH09JyR7ZGF0YVZhbHVlfSddYCA6IGBbJHtlbGVtZW50VG9TZWxlY3R9XWA7XHJcbiAgICAgICAgY29uc3QgZWxlbWVudHMgPSB0aGlzLmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpO1xyXG4gICAgICAgIHJldHVybiBBcnJheS5mcm9tKGVsZW1lbnRzKSBhcyBIVE1MRWxlbWVudFtdO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICog0JLQvdGD0YLRgNC10L3QvdC40Lkg0LzQtdGC0L7QtCDQtNC70Y8g0L/QvtC70YPRh9C10L3QuNGPINGN0LvQtdC80LXQvdGC0LAg0YEg0LfQsNC00LXRgNC20LrQvtC5XHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIGlkZW50aWZpZXIgLSDQodC10LvQtdC60YLQvtGAINGN0LvQtdC80LXQvdGC0LBcclxuICAgICAqIEBwYXJhbSBzZWxlY3RvciAtINCc0LXRgtC+0LQg0L/QvtC40YHQutCwXHJcbiAgICAgKiBAcGFyYW0gbm9kZSAtINCa0L7RgNC90LXQstC+0Lkg0YPQt9C10LtcclxuICAgICAqIEBwYXJhbSB0aW1lIC0g0JLRgNC10LzRjyDQt9Cw0LTQtdGA0LbQutC4INCyINC80YFcclxuICAgICAqIEByZXR1cm5zINCf0YDQvtC80LjRgSDRgSDRgNC10LfRg9C70YzRgtCw0YLQvtC8INC/0L7QuNGB0LrQsFxyXG4gICAgICogQHByaXZhdGVcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhc3luYyBfZ2V0RWxlbWVudFJlc3VsdChcclxuICAgICAgICBpZGVudGlmaWVyOiBzdHJpbmcsXHJcbiAgICAgICAgc2VsZWN0b3I6IFRTZWxlY3RvcixcclxuICAgICAgICBub2RlOiBEb2N1bWVudCB8IEhUTUxFbGVtZW50IHwgbnVsbCxcclxuICAgICAgICB0aW1lOiBudW1iZXJcclxuICAgICk6IFByb21pc2U8SFRNTEVsZW1lbnQ+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fc2V0RGVsYXkodGltZSlcclxuICAgICAgICAgICAgLnRoZW4oXyA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIW5vZGUpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIC8vINCY0YHQv9C+0LvRjNC30YPQtdC8IHR5cGUgYXNzZXJ0aW9uINC00LvRjyDQstGL0LfQvtCy0LAg0LzQtdGC0L7QtNCwXHJcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSAobm9kZSBhcyBhbnkpW3NlbGVjdG9yXShpZGVudGlmaWVyKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgfHwgbnVsbDtcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IGNvbnNvbGUubG9nKCfQntGI0LjQsdC60LAg0LIgX2dldEVsZW1lbnRSZXN1bHQnLCBlcnJvcikpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICog0KHQvtC30LTQsNC10YIgUHJvbWlzZSDRgSDQt9Cw0LTQtdGA0LbQutC+0LlcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gbXMgLSDQktGA0LXQvNGPINC30LDQtNC10YDQttC60Lgg0LIg0LzQuNC70LvQuNGB0LXQutGD0L3QtNCw0YVcclxuICAgICAqIEByZXR1cm5zIFByb21pc2UsINC60L7RgtC+0YDRi9C5INGA0LDQt9GA0LXRiNCw0LXRgtGB0Y8g0YfQtdGA0LXQtyDRg9C60LDQt9Cw0L3QvdC+0LUg0LLRgNC10LzRj1xyXG4gICAgICogQHByaXZhdGVcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBfc2V0RGVsYXkobXM6IG51bWJlcik6IFByb21pc2U8dW5rbm93bj4ge1xyXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqINCS0L7Qt9Cy0YDQsNGJ0LDQtdGCINGA0LDQt9C80LXRgNGLINGN0LvQtdC80LXQvdGC0LAg0Lgg0LXQs9C+INC/0L7Qu9C+0LbQtdC90LjQtSDQvtGC0L3QvtGB0LjRgtC10LvRjNC90L4gdmlld3BvcnRcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gZWxlbWVudCAtINCm0LXQu9C10LLQvtC5IERPTSDRjdC70LXQvNC10L3RglxyXG4gICAgICogQHJldHVybnMgRE9NUmVjdCDQvtCx0YrQtdC60YIg0YEg0LrQvtC+0YDQtNC40L3QsNGC0LDQvNC4ICh0b3AsIGxlZnQsIHJpZ2h0LCBib3R0b20pINC4INGA0LDQt9C80LXRgNCw0LzQuCAod2lkdGgsIGhlaWdodClcclxuICAgICAqIEB0aHJvd3Mge0Vycm9yfSDQldGB0LvQuCBlbGVtZW50INC90LUg0YPQutCw0LfQsNC9XHJcbiAgICAgKlxyXG4gICAgICogQGV4YW1wbGVcclxuICAgICAqIGNvbnN0IHJlY3QgPSB3b3JrZXIuZ2V0Q29vcmRpbmF0ZXMoYnV0dG9uRWxlbWVudCk7XHJcbiAgICAgKiBjb25zb2xlLmxvZyhyZWN0LnRvcCwgcmVjdC5sZWZ0LCByZWN0LndpZHRoKTtcclxuICAgICAqL1xyXG4gICAgZ2V0Q29vcmRpbmF0ZXMoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBET01SZWN0IHtcclxuICAgICAgICBpZiAoIWVsZW1lbnQpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFbGVtZW50IGlzIHJlcXVpcmVkIGZvciBnZXRDb29yZGluYXRlcycpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqINCS0L7Qt9Cy0YDQsNGJ0LDQtdGCINGA0L7QtNC40YLQtdC70YzRgdC60LjQuSDRjdC70LXQvNC10L3RgiDRg9C60LDQt9Cw0L3QvdC+0LPQviBET00g0YPQt9C70LBcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gZWwgLSBET00g0Y3Qu9C10LzQtdC90YIg0LjQu9C4IE5vZGVMaXN0XHJcbiAgICAgKiBAcmV0dXJucyDQoNC+0LTQuNGC0LXQu9GM0YHQutC40Lkg0Y3Qu9C10LzQtdC90YIg0LjQu9C4IG51bGwsINC10YHQu9C4INGA0L7QtNC40YLQtdC70Y8g0L3QtdGCXHJcbiAgICAgKi9cclxuICAgIGVsZW1lbnRHZXRQYXJlbnQoZWw6IEVsZW1lbnQgfCBOb2RlTGlzdCk6IE5vZGUgJiBQYXJlbnROb2RlIHwgbnVsbCB7XHJcbiAgICAgICAgaWYgKGVsICYmICdwYXJlbnROb2RlJyBpbiBlbCkge1xyXG4gICAgICAgICAgICByZXR1cm4gZWwucGFyZW50Tm9kZSBhcyBOb2RlICYgUGFyZW50Tm9kZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICog0JLQvtC30LLRgNCw0YnQsNC10YIg0LLRgdC1INGB0L7RgdC10LTQvdC40LUg0Y3Qu9C10LzQtdC90YLRiyAo0LLQutC70Y7Rh9Cw0Y8g0YHQsNC8INGN0LvQtdC80LXQvdGCKVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBlbCAtINCY0YHRhdC+0LTQvdGL0LkgRE9NINGN0LvQtdC80LXQvdGCXHJcbiAgICAgKiBAcmV0dXJucyDQnNCw0YHRgdC40LIg0LLRgdC10YUg0Y3Qu9C10LzQtdC90YLQvtCyINCyINGC0LXQutGD0YnQtdC5INCy0LXRgtC60LUgRE9NINC00LXRgNC10LLQsFxyXG4gICAgICpcclxuICAgICAqIEByZW1hcmtzXHJcbiAgICAgKiDQnNC10YLQvtC0INGB0L7QsdC40YDQsNC10YIg0LLRgdC1INGN0LvQtdC80LXQvdGC0Ysg0L3QsCDQvtC00L3QvtC8INGD0YDQvtCy0L3QtSDQstC70L7QttC10L3QvdC+0YHRgtC4XHJcbiAgICAgKi9cclxuICAgIGVsZW1lbnRzR2V0U2libGluZ0FsbChlbDogRWxlbWVudCB8IE5vZGVMaXN0KTogRWxlbWVudFtdIHtcclxuICAgICAgICBpZiAoZWwgJiYgJ3BhcmVudE5vZGUnIGluIGVsKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHBhcmVudCA9IGVsLnBhcmVudE5vZGUgYXMgTm9kZSAmIFBhcmVudE5vZGU7XHJcbiAgICAgICAgICAgIGNvbnN0IGZpcnN0RWxlbWVudCA9IHBhcmVudC5maXJzdENoaWxkIGFzIEVsZW1lbnQ7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVsZW1lbnRHZXRTaWJsaW5nTmV4dChmaXJzdEVsZW1lbnQpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gW107XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDQktC+0LfQstGA0LDRidCw0LXRgiDQstGB0LUg0YHQu9C10LTRg9GO0YnQuNC1INGB0L7RgdC10LTQvdC40LUg0Y3Qu9C10LzQtdC90YLRiyAobmV4dEVsZW1lbnRTaWJsaW5nKVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBlbCAtINCY0YHRhdC+0LTQvdGL0LkgRE9NINGN0LvQtdC80LXQvdGCXHJcbiAgICAgKiBAcmV0dXJucyDQnNCw0YHRgdC40LIg0Y3Qu9C10LzQtdC90YLQvtCyLCDQvdCw0YfQuNC90LDRjyDRgSDRg9C60LDQt9Cw0L3QvdC+0LPQviDQuCDQstC60LvRjtGH0LDRjyDQstGB0LUg0YHQu9C10LTRg9GO0YnQuNC1XHJcbiAgICAgKlxyXG4gICAgICogQGV4YW1wbGVcclxuICAgICAqIGNvbnN0IG5leHRFbGVtZW50cyA9IHdvcmtlci5lbGVtZW50R2V0U2libGluZ05leHQoY3VycmVudEVsZW1lbnQpO1xyXG4gICAgICogLy8g0JLQvtC30LLRgNCw0YnQsNC10YIgW2N1cnJlbnRFbGVtZW50LCBuZXh0RWxlbWVudCwgbmV4dE5leHRFbGVtZW50LCAuLi5dXHJcbiAgICAgKi9cclxuICAgIGVsZW1lbnRHZXRTaWJsaW5nTmV4dChlbDogRWxlbWVudCB8IE5vZGVMaXN0KTogRWxlbWVudFtdIHtcclxuICAgICAgICBjb25zdCByZXN1bHQ6IEVsZW1lbnRbXSA9IFtdO1xyXG5cclxuICAgICAgICB3aGlsZSAoZWwpIHtcclxuICAgICAgICAgICAgaWYgKCduZXh0RWxlbWVudFNpYmxpbmcnIGluIGVsKSB7XHJcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaChlbCBhcyBFbGVtZW50KTtcclxuICAgICAgICAgICAgICAgIGVsID0gKGVsIGFzIEVsZW1lbnQpLm5leHRFbGVtZW50U2libGluZyBhcyBFbGVtZW50O1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDQktC+0LfQstGA0LDRidCw0LXRgiDQstGB0LUg0L/RgNC10LTRi9C00YPRidC40LUg0YHQvtGB0LXQtNC90LjQtSDRjdC70LXQvNC10L3RgtGLIChwcmV2aW91c1NpYmxpbmcpXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIGVsIC0g0JjRgdGF0L7QtNC90YvQuSBET00g0Y3Qu9C10LzQtdC90YJcclxuICAgICAqIEByZXR1cm5zINCc0LDRgdGB0LjQsiDQv9GA0LXQtNGL0LTRg9GJ0LjRhSDRjdC70LXQvNC10L3RgtC+0LJcclxuICAgICAqXHJcbiAgICAgKiBAcmVtYXJrc1xyXG4gICAgICog0JLQvtC30LLRgNCw0YnQsNC10YIg0LLRgdC1INGN0LvQtdC80LXQvdGC0YssINCy0LrQu9GO0YfQsNGPINGD0LrQsNC30LDQvdC90YvQuSwg0LIg0L7QsdGA0LDRgtC90L7QvCDQv9C+0YDRj9C00LrQtVxyXG4gICAgICovXHJcbiAgICBlbGVtZW50R2V0U2libGluZ1ByZXZpb3VzKGVsOiBFbGVtZW50IHwgTm9kZUxpc3QgfCBOb2RlKTogRWxlbWVudFtdIHtcclxuICAgICAgICBjb25zdCByZXN1bHQ6IEVsZW1lbnRbXSA9IFtdO1xyXG4gICAgICAgIGxldCBjdXJyZW50OiBOb2RlIHwgbnVsbCA9IGVsIGFzIE5vZGU7XHJcblxyXG4gICAgICAgIHdoaWxlIChjdXJyZW50KSB7XHJcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKGN1cnJlbnQgYXMgRWxlbWVudCk7XHJcbiAgICAgICAgICAgIGN1cnJlbnQgPSBjdXJyZW50LnByZXZpb3VzU2libGluZztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiDQktC+0LfQstGA0LDRidCw0LXRgiDQstGB0LUg0L/RgNGP0LzRi9C1INC00L7Rh9C10YDQvdC40LUg0Y3Qu9C10LzQtdC90YLRiyDRg9C60LDQt9Cw0L3QvdC+0LPQviDRgNC+0LTQuNGC0LXQu9GPXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIGVsIC0g0KDQvtC00LjRgtC10LvRjNGB0LrQuNC5IERPTSDRjdC70LXQvNC10L3RglxyXG4gICAgICogQHJldHVybnMg0JzQsNGB0YHQuNCyINC00L7Rh9C10YDQvdC40YUg0Y3Qu9C10LzQtdC90YLQvtCyXHJcbiAgICAgKlxyXG4gICAgICogQGV4YW1wbGVcclxuICAgICAqIGNvbnN0IGNoaWxkcmVuID0gd29ya2VyLmVsZW1lbnRHZXRDaGlsZHJlbihwYXJlbnRFbGVtZW50KTtcclxuICAgICAqIGNoaWxkcmVuLmZvckVhY2goY2hpbGQgPT4gY29uc29sZS5sb2coY2hpbGQudGFnTmFtZSkpO1xyXG4gICAgICovXHJcbiAgICBlbGVtZW50R2V0Q2hpbGRyZW4oZWw6IEVsZW1lbnQpOiBFbGVtZW50W10ge1xyXG4gICAgICAgIHJldHVybiBBcnJheS5mcm9tKGVsLmNoaWxkcmVuKSBhcyBFbGVtZW50W107XHJcbiAgICB9XHJcbn1cclxuIl19
|