@libs-ui/components-inputs-mention 0.1.1-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/defines/caret-coords.define.d.ts +5 -0
- package/defines/template.define.d.ts +4 -0
- package/defines/utils.define.d.ts +18 -0
- package/esm2022/defines/caret-coords.define.mjs +115 -0
- package/esm2022/defines/template.define.mjs +26 -0
- package/esm2022/defines/utils.define.mjs +279 -0
- package/esm2022/index.mjs +3 -0
- package/esm2022/interfaces/mention.interface.mjs +2 -0
- package/esm2022/libs-ui-components-inputs-mention.mjs +5 -0
- package/esm2022/list/list.component.mjs +165 -0
- package/esm2022/mention.directive.mjs +507 -0
- package/fesm2022/libs-ui-components-inputs-mention.mjs +1084 -0
- package/fesm2022/libs-ui-components-inputs-mention.mjs.map +1 -0
- package/index.d.ts +2 -0
- package/interfaces/mention.interface.d.ts +40 -0
- package/list/list.component.d.ts +36 -0
- package/mention.directive.d.ts +49 -0
- package/package.json +30 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, model, signal, viewChild, viewChildren } from '@angular/core';
|
|
2
|
+
import { LibsUiComponentsAvatarComponent } from '@libs-ui/components-avatar';
|
|
3
|
+
import { LibsUiComponentsPopoverComponent } from '@libs-ui/components-popover';
|
|
4
|
+
import { set } from '@libs-ui/utils';
|
|
5
|
+
import { fromEvent, Subject, takeUntil } from 'rxjs';
|
|
6
|
+
import { getCaretCoordinates } from '../defines/caret-coords.define';
|
|
7
|
+
import { UtilsKeyCodeConstant } from '@libs-ui/utils';
|
|
8
|
+
import { getContentEditableCaretCoords, isInputOrTextAreaElement } from '../defines/utils.define';
|
|
9
|
+
import * as i0 from "@angular/core";
|
|
10
|
+
export class LibsUiComponentsInputsMentionListComponent {
|
|
11
|
+
// #region PROPERTY
|
|
12
|
+
items = signal([]);
|
|
13
|
+
activeIndex = signal(0);
|
|
14
|
+
hidden = signal(false);
|
|
15
|
+
styleOff = signal(false);
|
|
16
|
+
parentHandlerKeyDown = signal(undefined);
|
|
17
|
+
dropUp = signal(false);
|
|
18
|
+
coords = signal({ top: 0, left: 0, bottom: 0 });
|
|
19
|
+
offset = signal(0);
|
|
20
|
+
nativeParentElement = signal(undefined);
|
|
21
|
+
onDestroy = new Subject();
|
|
22
|
+
// #region INPUT
|
|
23
|
+
labelKey = model('label');
|
|
24
|
+
zIndex = model(1000);
|
|
25
|
+
isIframe = model.required();
|
|
26
|
+
defaultAvatar = model();
|
|
27
|
+
/* VIEW CHILD */
|
|
28
|
+
elementEl = viewChild('element');
|
|
29
|
+
itemsEl = viewChildren('item');
|
|
30
|
+
ngOnInit() {
|
|
31
|
+
if (this.isIframe()) {
|
|
32
|
+
this.initEvent(window.parent, 'wheel');
|
|
33
|
+
this.initEvent(window.parent, 'resize');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
this.initEvent(window, 'wheel');
|
|
37
|
+
this.initEvent(window, 'resize');
|
|
38
|
+
}
|
|
39
|
+
/* FUNCTIONS */
|
|
40
|
+
initEvent(element, eventName) {
|
|
41
|
+
fromEvent(element, eventName)
|
|
42
|
+
.pipe(takeUntil(this.onDestroy))
|
|
43
|
+
.subscribe((event) => {
|
|
44
|
+
if (eventName === 'resize' || !this.elementEl()?.nativeElement.contains(event.target)) {
|
|
45
|
+
this.handlerListenClose(event);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
handlerListenClose(event) {
|
|
50
|
+
if (event.target !== this.elementEl()?.nativeElement) {
|
|
51
|
+
this.hidden.set(true);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// lots of confusion here between relative coordinates and containers
|
|
55
|
+
position(nativeParentElement, iframe, leftDiv) {
|
|
56
|
+
this.nativeParentElement.set(nativeParentElement);
|
|
57
|
+
if (isInputOrTextAreaElement(nativeParentElement)) {
|
|
58
|
+
// parent elements need to have postition:relative for this to work correctly?
|
|
59
|
+
this.coords.set(getCaretCoordinates(nativeParentElement, nativeParentElement.selectionStart));
|
|
60
|
+
this.coords.update((item) => ({
|
|
61
|
+
...item,
|
|
62
|
+
top: nativeParentElement.offsetTop + item.top - nativeParentElement.scrollTop,
|
|
63
|
+
left: nativeParentElement.offsetLeft + item.left - nativeParentElement.scrollLeft + nativeParentElement.getBoundingClientRect().left,
|
|
64
|
+
}));
|
|
65
|
+
// getCretCoordinates() for text/input elements needs an additional offset to position the list correctly
|
|
66
|
+
this.offset.set(this.getBlockCursorDimensions(nativeParentElement).height);
|
|
67
|
+
this.positionElement();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (iframe) {
|
|
71
|
+
const context = { iframe: iframe, parent: window.parent.document.body, windowParent: true };
|
|
72
|
+
// const rect = iframe.getBoundingClientRect();
|
|
73
|
+
const caretRelativeToView = getContentEditableCaretCoords(context);
|
|
74
|
+
const doc = document.documentElement;
|
|
75
|
+
const scrollLeft = (window.scrollX || doc.scrollLeft) - (doc.clientLeft || 0);
|
|
76
|
+
this.coords.update((item) => ({
|
|
77
|
+
...item,
|
|
78
|
+
left: caretRelativeToView.left - scrollLeft - (leftDiv || 0),
|
|
79
|
+
bottom: window.parent.innerHeight - caretRelativeToView.top + 18,
|
|
80
|
+
}));
|
|
81
|
+
if (caretRelativeToView.bottom && caretRelativeToView.bottom !== -1) {
|
|
82
|
+
this.coords.update((item) => ({
|
|
83
|
+
...item,
|
|
84
|
+
bottom: caretRelativeToView.bottom,
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
this.positionElement();
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const doc = document.documentElement;
|
|
91
|
+
const scrollLeft = (window.scrollX || doc.scrollLeft) - (doc.clientLeft || 0);
|
|
92
|
+
const scrollTop = (window.scrollX || doc.scrollTop) - (doc.clientTop || 0);
|
|
93
|
+
// bounding rectangles are relative to view, offsets are relative to container?
|
|
94
|
+
const caretRelativeToView = getContentEditableCaretCoords({ iframe, parent: null });
|
|
95
|
+
this.coords.update((item) => ({
|
|
96
|
+
...item,
|
|
97
|
+
top: caretRelativeToView.top - scrollTop + 10,
|
|
98
|
+
left: caretRelativeToView.left - scrollLeft - (leftDiv || 0),
|
|
99
|
+
bottom: caretRelativeToView.bottom,
|
|
100
|
+
}));
|
|
101
|
+
this.positionElement();
|
|
102
|
+
}
|
|
103
|
+
get ActiveItem() {
|
|
104
|
+
return this.items()[this.activeIndex()];
|
|
105
|
+
}
|
|
106
|
+
handlerClick(event, index) {
|
|
107
|
+
event.stopPropagation();
|
|
108
|
+
this.activeIndex.set(index);
|
|
109
|
+
set(event, 'keyCode', UtilsKeyCodeConstant.ENTER);
|
|
110
|
+
this.parentHandlerKeyDown()?.(event, this.nativeParentElement());
|
|
111
|
+
}
|
|
112
|
+
activateNextItem() {
|
|
113
|
+
this.activeIndex.set(this.items().length - 1 > this.activeIndex() ? this.activeIndex() + 1 : this.activeIndex());
|
|
114
|
+
this.scrollToActive();
|
|
115
|
+
}
|
|
116
|
+
activatePreviousItem() {
|
|
117
|
+
this.activeIndex.set(this.activeIndex() > 0 ? this.activeIndex() - 1 : this.activeIndex());
|
|
118
|
+
this.scrollToActive();
|
|
119
|
+
}
|
|
120
|
+
positionElement(left = this.coords().left, top = this.coords().top, dropUp = this.dropUp(), bottom = this.coords().bottom || 0) {
|
|
121
|
+
const el = this.elementEl()?.nativeElement;
|
|
122
|
+
top += dropUp ? 0 : this.offset(); // top of list is next line
|
|
123
|
+
el.style.position = 'absolute';
|
|
124
|
+
el.style.left = left + 'px';
|
|
125
|
+
el.style.top = bottom !== -1 ? 'auto' : top + 'px';
|
|
126
|
+
el.style.bottom = bottom === -1 ? 'auto' : bottom + 'px';
|
|
127
|
+
this.nativeParentElement()?.normalize();
|
|
128
|
+
}
|
|
129
|
+
getBlockCursorDimensions(nativeParentElement) {
|
|
130
|
+
const parentStyles = window.getComputedStyle(nativeParentElement);
|
|
131
|
+
return {
|
|
132
|
+
height: parseFloat(parentStyles.lineHeight),
|
|
133
|
+
width: parseFloat(parentStyles.fontSize),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
handleActiveItem(event, index) {
|
|
137
|
+
event.stopPropagation();
|
|
138
|
+
this.activeIndex.set(index);
|
|
139
|
+
}
|
|
140
|
+
scrollToActive() {
|
|
141
|
+
if (!this.itemsEl() || this.itemsEl().length <= this.activeIndex()) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
this.itemsEl()[this.activeIndex()].nativeElement.scrollIntoView();
|
|
145
|
+
}
|
|
146
|
+
scrollContent() {
|
|
147
|
+
setTimeout(() => {
|
|
148
|
+
const element = this.elementEl();
|
|
149
|
+
if (element && element.nativeElement) {
|
|
150
|
+
element.nativeElement.scrollTop = 0;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
ngOnDestroy() {
|
|
155
|
+
this.onDestroy.next();
|
|
156
|
+
this.onDestroy.complete();
|
|
157
|
+
}
|
|
158
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LibsUiComponentsInputsMentionListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
159
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: LibsUiComponentsInputsMentionListComponent, isStandalone: true, selector: "libs_ui-components-inputs-mention-list", inputs: { labelKey: { classPropertyName: "labelKey", publicName: "labelKey", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, isIframe: { classPropertyName: "isIframe", publicName: "isIframe", isSignal: true, isRequired: true, transformFunction: null }, defaultAvatar: { classPropertyName: "defaultAvatar", publicName: "defaultAvatar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { labelKey: "labelKeyChange", zIndex: "zIndexChange", isIframe: "isIframeChange", defaultAvatar: "defaultAvatarChange" }, viewQueries: [{ propertyName: "elementEl", first: true, predicate: ["element"], descendants: true, isSignal: true }, { propertyName: "itemsEl", predicate: ["item"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #element\n class=\"libs-ui-mention-list\"\n [style.zIndex]=\"zIndex()\"\n [class.hidden]=\"hidden()\">\n @for (item of items(); track item) {\n <div\n #item\n class=\"libs-ui-mention-list-item\"\n [class.libs-ui-mention-list-item-active]=\"$index === activeIndex()\"\n (mousedown)=\"handlerClick($event, $index)\"\n (mouseenter)=\"handleActiveItem($event, $index)\">\n <div class=\"px-[12px] py-[6px] flex items-center\">\n <libs_ui-components-avatar\n [size]=\"24\"\n [linkAvatar]=\"item.avatar\"\n [linkAvatarError]=\"defaultAvatar()\"\n [getLastTextAfterSpace]=\"true\"\n [textAvatar]=\"item.name\"\n [idGenColor]=\"item.id\" />\n <libs_ui-components-popover\n [classInclude]=\"'libs-ui-font-h5r'\"\n [type]=\"'text'\"\n [ignoreShowPopover]=\"true\"\n [config]=\"{ width: 250 }\">\n <!-- // ta.m \u1EA9n show tooltip v\u00EC ch\u01B0a x\u1EED l\u00FD \u0111c v\u1ECB tr\u00ED -->\n {{ item.name + ' (' + item.username + ')' }}\n </libs_ui-components-popover>\n </div>\n </div>\n }\n</div>\n", styles: [".libs-ui-mention-list{position:absolute;top:-999px;left:-9999px;z-index:1202;float:left;width:315px;padding:4px 0;background-color:#fff;border:solid 1px #e6e8ed;border-radius:5px;max-height:190px;overflow:auto;box-shadow:0 2px 10px 1px #3333331a}.libs-ui-mention-list .libs-ui-mention-list-item{background:#fff;cursor:pointer}.libs-ui-mention-list .libs-ui-mention-list-item:hover,.libs-ui-mention-list .libs-ui-mention-list-item-active{background-color:var(--libs-ui-color-light-3, #f4f8ff)}\n"], dependencies: [{ kind: "component", type: LibsUiComponentsAvatarComponent, selector: "libs_ui-components-avatar", inputs: ["typeShape", "classInclude", "size", "linkAvatar", "linkAvatarError", "classImageInclude", "zIndexPreviewImage", "clickPreviewImage", "idGenColor", "getLastTextAfterSpace", "textAvatar", "textAvatarClassInclude", "containertextAvatarClassInclude"], outputs: ["outAvatarError", "outEventPreviewImage"] }, { kind: "component", type: LibsUiComponentsPopoverComponent, selector: "libs_ui-components-popover,[LibsUiComponentsPopoverDirective]", inputs: ["debugId", "flagMouse", "type", "mode", "config", "ignoreShowPopover", "elementRefCustom", "initEventInElementRefCustom", "classInclude", "ignoreHiddenPopoverContentWhenMouseLeave", "ignoreStopPropagationEvent", "ignoreCursorPointerModeLikeClick", "isAddContentToParentDocument", "ignoreClickOutside"], outputs: ["outEvent", "outChangStageFlagMouse", "outEventPopoverContent", "outFunctionsControl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
160
|
+
}
|
|
161
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LibsUiComponentsInputsMentionListComponent, decorators: [{
|
|
162
|
+
type: Component,
|
|
163
|
+
args: [{ selector: 'libs_ui-components-inputs-mention-list', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [LibsUiComponentsAvatarComponent, LibsUiComponentsPopoverComponent], template: "<div\n #element\n class=\"libs-ui-mention-list\"\n [style.zIndex]=\"zIndex()\"\n [class.hidden]=\"hidden()\">\n @for (item of items(); track item) {\n <div\n #item\n class=\"libs-ui-mention-list-item\"\n [class.libs-ui-mention-list-item-active]=\"$index === activeIndex()\"\n (mousedown)=\"handlerClick($event, $index)\"\n (mouseenter)=\"handleActiveItem($event, $index)\">\n <div class=\"px-[12px] py-[6px] flex items-center\">\n <libs_ui-components-avatar\n [size]=\"24\"\n [linkAvatar]=\"item.avatar\"\n [linkAvatarError]=\"defaultAvatar()\"\n [getLastTextAfterSpace]=\"true\"\n [textAvatar]=\"item.name\"\n [idGenColor]=\"item.id\" />\n <libs_ui-components-popover\n [classInclude]=\"'libs-ui-font-h5r'\"\n [type]=\"'text'\"\n [ignoreShowPopover]=\"true\"\n [config]=\"{ width: 250 }\">\n <!-- // ta.m \u1EA9n show tooltip v\u00EC ch\u01B0a x\u1EED l\u00FD \u0111c v\u1ECB tr\u00ED -->\n {{ item.name + ' (' + item.username + ')' }}\n </libs_ui-components-popover>\n </div>\n </div>\n }\n</div>\n", styles: [".libs-ui-mention-list{position:absolute;top:-999px;left:-9999px;z-index:1202;float:left;width:315px;padding:4px 0;background-color:#fff;border:solid 1px #e6e8ed;border-radius:5px;max-height:190px;overflow:auto;box-shadow:0 2px 10px 1px #3333331a}.libs-ui-mention-list .libs-ui-mention-list-item{background:#fff;cursor:pointer}.libs-ui-mention-list .libs-ui-mention-list-item:hover,.libs-ui-mention-list .libs-ui-mention-list-item-active{background-color:var(--libs-ui-color-light-3, #f4f8ff)}\n"] }]
|
|
164
|
+
}] });
|
|
165
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvaW5wdXRzL21lbnRpb24vc3JjL2xpc3QvbGlzdC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvaW5wdXRzL21lbnRpb24vc3JjL2xpc3QvbGlzdC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFjLEtBQUssRUFBcUIsTUFBTSxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUksT0FBTyxFQUFFLCtCQUErQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDN0UsT0FBTyxFQUFFLGdDQUFnQyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDL0UsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3JDLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNyRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNyRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0RCxPQUFPLEVBQUUsNkJBQTZCLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQzs7QUFXbEcsTUFBTSxPQUFPLDBDQUEwQztJQUNyRCxtQkFBbUI7SUFDWixLQUFLLEdBQUcsTUFBTSxDQUE0QyxFQUFFLENBQUMsQ0FBQztJQUM5RCxXQUFXLEdBQUcsTUFBTSxDQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ2hDLE1BQU0sR0FBRyxNQUFNLENBQVUsS0FBSyxDQUFDLENBQUM7SUFDaEMsUUFBUSxHQUFHLE1BQU0sQ0FBVSxLQUFLLENBQUMsQ0FBQztJQUNsQyxvQkFBb0IsR0FBRyxNQUFNLENBQTZFLFNBQVMsQ0FBQyxDQUFDO0lBRWxILE1BQU0sR0FBRyxNQUFNLENBQVUsS0FBSyxDQUFDLENBQUM7SUFFbEMsTUFBTSxHQUFHLE1BQU0sQ0FBaUQsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDaEcsTUFBTSxHQUFHLE1BQU0sQ0FBUyxDQUFDLENBQUMsQ0FBQztJQUMzQixtQkFBbUIsR0FBRyxNQUFNLENBQStCLFNBQVMsQ0FBQyxDQUFDO0lBQ3RFLFNBQVMsR0FBRyxJQUFJLE9BQU8sRUFBUSxDQUFDO0lBRXhDLGdCQUFnQjtJQUNoQixRQUFRLEdBQUcsS0FBSyxDQUFTLE9BQU8sQ0FBQyxDQUFDO0lBQ2xDLE1BQU0sR0FBRyxLQUFLLENBQVMsSUFBSSxDQUFDLENBQUM7SUFDN0IsUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQVcsQ0FBQztJQUNyQyxhQUFhLEdBQUcsS0FBSyxFQUFVLENBQUM7SUFFaEMsZ0JBQWdCO0lBQ1AsU0FBUyxHQUFHLFNBQVMsQ0FBYSxTQUFTLENBQUMsQ0FBQztJQUM3QyxPQUFPLEdBQUcsWUFBWSxDQUFhLE1BQU0sQ0FBQyxDQUFDO0lBRXBELFFBQVE7UUFDTixJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUN2QyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDeEMsT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNoQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNuQyxDQUFDO0lBRUQsZUFBZTtJQUNQLFNBQVMsQ0FBQyxPQUFlLEVBQUUsU0FBaUI7UUFDbEQsU0FBUyxDQUFRLE9BQU8sRUFBRSxTQUFTLENBQUM7YUFDakMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7YUFDL0IsU0FBUyxDQUFDLENBQUMsS0FBWSxFQUFFLEVBQUU7WUFDMUIsSUFBSSxTQUFTLEtBQUssUUFBUSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLGFBQWEsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7Z0JBQ3RGLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNqQyxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRU8sa0JBQWtCLENBQUMsS0FBWTtRQUNyQyxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLGFBQWEsRUFBRSxDQUFDO1lBQ3JELElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3hCLENBQUM7SUFDSCxDQUFDO0lBRUQscUVBQXFFO0lBQ3JFLFFBQVEsQ0FBQyxtQkFBcUMsRUFBRSxNQUEwQixFQUFFLE9BQWdCO1FBQzFGLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNsRCxJQUFJLHdCQUF3QixDQUFDLG1CQUFtQixDQUFDLEVBQUUsQ0FBQztZQUNsRCw4RUFBOEU7WUFDOUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLENBQUMsbUJBQW1CLEVBQUUsbUJBQW1CLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztZQUM5RixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDNUIsR0FBRyxJQUFJO2dCQUNQLEdBQUcsRUFBRSxtQkFBbUIsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsR0FBRyxtQkFBbUIsQ0FBQyxTQUFTO2dCQUM3RSxJQUFJLEVBQUUsbUJBQW1CLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLEdBQUcsbUJBQW1CLENBQUMsVUFBVSxHQUFHLG1CQUFtQixDQUFDLHFCQUFxQixFQUFFLENBQUMsSUFBSTthQUNySSxDQUFDLENBQUMsQ0FBQztZQUVKLHlHQUF5RztZQUN6RyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUMzRSxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDdkIsT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1gsTUFBTSxPQUFPLEdBQWtGLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsQ0FBQztZQUMzSywrQ0FBK0M7WUFDL0MsTUFBTSxtQkFBbUIsR0FBRyw2QkFBNkIsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNuRSxNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsZUFBZSxDQUFDO1lBQ3JDLE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxDQUFDLE9BQU8sSUFBSSxHQUFHLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsVUFBVSxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQzlFLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUM1QixHQUFHLElBQUk7Z0JBQ1AsSUFBSSxFQUFFLG1CQUFtQixDQUFDLElBQUksR0FBRyxVQUFVLEdBQUcsQ0FBQyxPQUFPLElBQUksQ0FBQyxDQUFDO2dCQUM1RCxNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEdBQUcsbUJBQW1CLENBQUMsR0FBRyxHQUFHLEVBQUU7YUFDakUsQ0FBQyxDQUFDLENBQUM7WUFDSixJQUFJLG1CQUFtQixDQUFDLE1BQU0sSUFBSSxtQkFBbUIsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDcEUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7b0JBQzVCLEdBQUcsSUFBSTtvQkFDUCxNQUFNLEVBQUUsbUJBQW1CLENBQUMsTUFBTTtpQkFDbkMsQ0FBQyxDQUFDLENBQUM7WUFDTixDQUFDO1lBQ0QsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBRXZCLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLGVBQWUsQ0FBQztRQUNyQyxNQUFNLFVBQVUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLElBQUksR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUM5RSxNQUFNLFNBQVMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLElBQUksR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFNBQVMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUMzRSwrRUFBK0U7UUFDL0UsTUFBTSxtQkFBbUIsR0FBRyw2QkFBNkIsQ0FBQyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUVwRixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztZQUM1QixHQUFHLElBQUk7WUFDUCxHQUFHLEVBQUUsbUJBQW1CLENBQUMsR0FBRyxHQUFHLFNBQVMsR0FBRyxFQUFFO1lBQzdDLElBQUksRUFBRSxtQkFBbUIsQ0FBQyxJQUFJLEdBQUcsVUFBVSxHQUFHLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQztZQUM1RCxNQUFNLEVBQUUsbUJBQW1CLENBQUMsTUFBTTtTQUNuQyxDQUFDLENBQUMsQ0FBQztRQUNKLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBRUQsSUFBSSxVQUFVO1FBQ1osT0FBTyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVTLFlBQVksQ0FBQyxLQUFZLEVBQUUsS0FBYTtRQUNoRCxLQUFLLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDeEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDNUIsR0FBRyxDQUFDLEtBQXNCLEVBQUUsU0FBUyxFQUFFLG9CQUFvQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ25FLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxFQUFFLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLENBQUM7SUFDbkUsQ0FBQztJQUVELGdCQUFnQjtRQUNkLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDakgsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ3hCLENBQUM7SUFFRCxvQkFBb0I7UUFDbEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDM0YsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ3hCLENBQUM7SUFFTyxlQUFlLENBQUMsT0FBZSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLE1BQWMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsRUFBRSxTQUFrQixJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsU0FBaUIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLE1BQU0sSUFBSSxDQUFDO1FBQ3JLLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsRUFBRSxhQUFhLENBQUM7UUFFM0MsR0FBRyxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQywyQkFBMkI7UUFDOUQsRUFBRSxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsVUFBVSxDQUFDO1FBQy9CLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7UUFDNUIsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsTUFBTSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUM7UUFDbkQsRUFBRSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsTUFBTSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7UUFDekQsSUFBSSxDQUFDLG1CQUFtQixFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUM7SUFDMUMsQ0FBQztJQUVPLHdCQUF3QixDQUFDLG1CQUFxQztRQUNwRSxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUVsRSxPQUFPO1lBQ0wsTUFBTSxFQUFFLFVBQVUsQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDO1lBQzNDLEtBQUssRUFBRSxVQUFVLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQztTQUN6QyxDQUFDO0lBQ0osQ0FBQztJQUVTLGdCQUFnQixDQUFDLEtBQVksRUFBRSxLQUFhO1FBQ3BELEtBQUssQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBRU8sY0FBYztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUM7WUFDbkUsT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsYUFBYSxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ3BFLENBQUM7SUFFRCxhQUFhO1FBQ1gsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUNkLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNqQyxJQUFJLE9BQU8sSUFBSSxPQUFPLENBQUMsYUFBYSxFQUFFLENBQUM7Z0JBQ3JDLE9BQU8sQ0FBQyxhQUFhLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQztZQUN0QyxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUM1QixDQUFDO3dHQTFLVSwwQ0FBMEM7NEZBQTFDLDBDQUEwQyx3OEJDbEJ2RCwwcENBZ0NBLHdpQkRoQlksK0JBQStCLDZYQUFFLGdDQUFnQzs7NEZBRWhFLDBDQUEwQztrQkFUdEQsU0FBUzsrQkFFRSx3Q0FBd0MsY0FHdEMsSUFBSSxtQkFDQyx1QkFBdUIsQ0FBQyxNQUFNLFdBQ3RDLENBQUMsK0JBQStCLEVBQUUsZ0NBQWdDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBtb2RlbCwgT25EZXN0cm95LCBPbkluaXQsIHNpZ25hbCwgdmlld0NoaWxkLCB2aWV3Q2hpbGRyZW4gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IExpYnNVaUNvbXBvbmVudHNBdmF0YXJDb21wb25lbnQgfSBmcm9tICdAbGlicy11aS9jb21wb25lbnRzLWF2YXRhcic7XG5pbXBvcnQgeyBMaWJzVWlDb21wb25lbnRzUG9wb3ZlckNvbXBvbmVudCB9IGZyb20gJ0BsaWJzLXVpL2NvbXBvbmVudHMtcG9wb3Zlcic7XG5pbXBvcnQgeyBzZXQgfSBmcm9tICdAbGlicy11aS91dGlscyc7XG5pbXBvcnQgeyBmcm9tRXZlbnQsIFN1YmplY3QsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZ2V0Q2FyZXRDb29yZGluYXRlcyB9IGZyb20gJy4uL2RlZmluZXMvY2FyZXQtY29vcmRzLmRlZmluZSc7XG5pbXBvcnQgeyBVdGlsc0tleUNvZGVDb25zdGFudCB9IGZyb20gJ0BsaWJzLXVpL3V0aWxzJztcbmltcG9ydCB7IGdldENvbnRlbnRFZGl0YWJsZUNhcmV0Q29vcmRzLCBpc0lucHV0T3JUZXh0QXJlYUVsZW1lbnQgfSBmcm9tICcuLi9kZWZpbmVzL3V0aWxzLmRlZmluZSc7XG5cbkBDb21wb25lbnQoe1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQGFuZ3VsYXItZXNsaW50L2NvbXBvbmVudC1zZWxlY3RvclxuICBzZWxlY3RvcjogJ2xpYnNfdWktY29tcG9uZW50cy1pbnB1dHMtbWVudGlvbi1saXN0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2xpc3QuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9saXN0LmNvbXBvbmVudC5zY3NzJ10sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBpbXBvcnRzOiBbTGlic1VpQ29tcG9uZW50c0F2YXRhckNvbXBvbmVudCwgTGlic1VpQ29tcG9uZW50c1BvcG92ZXJDb21wb25lbnRdLFxufSlcbmV4cG9ydCBjbGFzcyBMaWJzVWlDb21wb25lbnRzSW5wdXRzTWVudGlvbkxpc3RDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIC8vICNyZWdpb24gUFJPUEVSVFlcbiAgcHVibGljIGl0ZW1zID0gc2lnbmFsPEFycmF5PFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IHVuZGVmaW5lZD4+PihbXSk7XG4gIHB1YmxpYyBhY3RpdmVJbmRleCA9IHNpZ25hbDxudW1iZXI+KDApO1xuICBwdWJsaWMgaGlkZGVuID0gc2lnbmFsPGJvb2xlYW4+KGZhbHNlKTtcbiAgcHVibGljIHN0eWxlT2ZmID0gc2lnbmFsPGJvb2xlYW4+KGZhbHNlKTtcbiAgcHVibGljIHBhcmVudEhhbmRsZXJLZXlEb3duID0gc2lnbmFsPCgoZTogRXZlbnQsIGVsZW1lbnQ6IEhUTUxJbnB1dEVsZW1lbnQgfCB1bmRlZmluZWQpID0+IHVua25vd24pIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuXG4gIHByb3RlY3RlZCBkcm9wVXAgPSBzaWduYWw8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gIHByaXZhdGUgY29vcmRzID0gc2lnbmFsPHsgdG9wOiBudW1iZXI7IGxlZnQ6IG51bWJlcjsgYm90dG9tPzogbnVtYmVyIH0+KHsgdG9wOiAwLCBsZWZ0OiAwLCBib3R0b206IDAgfSk7XG4gIHByaXZhdGUgb2Zmc2V0ID0gc2lnbmFsPG51bWJlcj4oMCk7XG4gIHByaXZhdGUgbmF0aXZlUGFyZW50RWxlbWVudCA9IHNpZ25hbDxIVE1MSW5wdXRFbGVtZW50IHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICBwcml2YXRlIG9uRGVzdHJveSA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgLy8gI3JlZ2lvbiBJTlBVVFxuICBsYWJlbEtleSA9IG1vZGVsPHN0cmluZz4oJ2xhYmVsJyk7XG4gIHpJbmRleCA9IG1vZGVsPG51bWJlcj4oMTAwMCk7XG4gIGlzSWZyYW1lID0gbW9kZWwucmVxdWlyZWQ8Ym9vbGVhbj4oKTtcbiAgZGVmYXVsdEF2YXRhciA9IG1vZGVsPHN0cmluZz4oKTtcblxuICAvKiBWSUVXIENISUxEICovXG4gIHJlYWRvbmx5IGVsZW1lbnRFbCA9IHZpZXdDaGlsZDxFbGVtZW50UmVmPignZWxlbWVudCcpO1xuICByZWFkb25seSBpdGVtc0VsID0gdmlld0NoaWxkcmVuPEVsZW1lbnRSZWY+KCdpdGVtJyk7XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgaWYgKHRoaXMuaXNJZnJhbWUoKSkge1xuICAgICAgdGhpcy5pbml0RXZlbnQod2luZG93LnBhcmVudCwgJ3doZWVsJyk7XG4gICAgICB0aGlzLmluaXRFdmVudCh3aW5kb3cucGFyZW50LCAncmVzaXplJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuaW5pdEV2ZW50KHdpbmRvdywgJ3doZWVsJyk7XG4gICAgdGhpcy5pbml0RXZlbnQod2luZG93LCAncmVzaXplJyk7XG4gIH1cblxuICAvKiBGVU5DVElPTlMgKi9cbiAgcHJpdmF0ZSBpbml0RXZlbnQoZWxlbWVudDogV2luZG93LCBldmVudE5hbWU6IHN0cmluZykge1xuICAgIGZyb21FdmVudDxFdmVudD4oZWxlbWVudCwgZXZlbnROYW1lKVxuICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMub25EZXN0cm95KSlcbiAgICAgIC5zdWJzY3JpYmUoKGV2ZW50OiBFdmVudCkgPT4ge1xuICAgICAgICBpZiAoZXZlbnROYW1lID09PSAncmVzaXplJyB8fCAhdGhpcy5lbGVtZW50RWwoKT8ubmF0aXZlRWxlbWVudC5jb250YWlucyhldmVudC50YXJnZXQpKSB7XG4gICAgICAgICAgdGhpcy5oYW5kbGVyTGlzdGVuQ2xvc2UoZXZlbnQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlckxpc3RlbkNsb3NlKGV2ZW50OiBFdmVudCkge1xuICAgIGlmIChldmVudC50YXJnZXQgIT09IHRoaXMuZWxlbWVudEVsKCk/Lm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgIHRoaXMuaGlkZGVuLnNldCh0cnVlKTtcbiAgICB9XG4gIH1cblxuICAvLyBsb3RzIG9mIGNvbmZ1c2lvbiBoZXJlIGJldHdlZW4gcmVsYXRpdmUgY29vcmRpbmF0ZXMgYW5kIGNvbnRhaW5lcnNcbiAgcG9zaXRpb24obmF0aXZlUGFyZW50RWxlbWVudDogSFRNTElucHV0RWxlbWVudCwgaWZyYW1lPzogSFRNTElGcmFtZUVsZW1lbnQsIGxlZnREaXY/OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLm5hdGl2ZVBhcmVudEVsZW1lbnQuc2V0KG5hdGl2ZVBhcmVudEVsZW1lbnQpO1xuICAgIGlmIChpc0lucHV0T3JUZXh0QXJlYUVsZW1lbnQobmF0aXZlUGFyZW50RWxlbWVudCkpIHtcbiAgICAgIC8vIHBhcmVudCBlbGVtZW50cyBuZWVkIHRvIGhhdmUgcG9zdGl0aW9uOnJlbGF0aXZlIGZvciB0aGlzIHRvIHdvcmsgY29ycmVjdGx5P1xuICAgICAgdGhpcy5jb29yZHMuc2V0KGdldENhcmV0Q29vcmRpbmF0ZXMobmF0aXZlUGFyZW50RWxlbWVudCwgbmF0aXZlUGFyZW50RWxlbWVudC5zZWxlY3Rpb25TdGFydCkpO1xuICAgICAgdGhpcy5jb29yZHMudXBkYXRlKChpdGVtKSA9PiAoe1xuICAgICAgICAuLi5pdGVtLFxuICAgICAgICB0b3A6IG5hdGl2ZVBhcmVudEVsZW1lbnQub2Zmc2V0VG9wICsgaXRlbS50b3AgLSBuYXRpdmVQYXJlbnRFbGVtZW50LnNjcm9sbFRvcCxcbiAgICAgICAgbGVmdDogbmF0aXZlUGFyZW50RWxlbWVudC5vZmZzZXRMZWZ0ICsgaXRlbS5sZWZ0IC0gbmF0aXZlUGFyZW50RWxlbWVudC5zY3JvbGxMZWZ0ICsgbmF0aXZlUGFyZW50RWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0LFxuICAgICAgfSkpO1xuXG4gICAgICAvLyBnZXRDcmV0Q29vcmRpbmF0ZXMoKSBmb3IgdGV4dC9pbnB1dCBlbGVtZW50cyBuZWVkcyBhbiBhZGRpdGlvbmFsIG9mZnNldCB0byBwb3NpdGlvbiB0aGUgbGlzdCBjb3JyZWN0bHlcbiAgICAgIHRoaXMub2Zmc2V0LnNldCh0aGlzLmdldEJsb2NrQ3Vyc29yRGltZW5zaW9ucyhuYXRpdmVQYXJlbnRFbGVtZW50KS5oZWlnaHQpO1xuICAgICAgdGhpcy5wb3NpdGlvbkVsZW1lbnQoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGlmcmFtZSkge1xuICAgICAgY29uc3QgY29udGV4dDogeyBpZnJhbWU6IEhUTUxJRnJhbWVFbGVtZW50OyBwYXJlbnQ6IEVsZW1lbnQgfCBudWxsOyB3aW5kb3dQYXJlbnQ/OiBib29sZWFuIH0gPSB7IGlmcmFtZTogaWZyYW1lLCBwYXJlbnQ6IHdpbmRvdy5wYXJlbnQuZG9jdW1lbnQuYm9keSwgd2luZG93UGFyZW50OiB0cnVlIH07XG4gICAgICAvLyBjb25zdCByZWN0ID0gaWZyYW1lLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgY29uc3QgY2FyZXRSZWxhdGl2ZVRvVmlldyA9IGdldENvbnRlbnRFZGl0YWJsZUNhcmV0Q29vcmRzKGNvbnRleHQpO1xuICAgICAgY29uc3QgZG9jID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICAgICAgY29uc3Qgc2Nyb2xsTGVmdCA9ICh3aW5kb3cuc2Nyb2xsWCB8fCBkb2Muc2Nyb2xsTGVmdCkgLSAoZG9jLmNsaWVudExlZnQgfHwgMCk7XG4gICAgICB0aGlzLmNvb3Jkcy51cGRhdGUoKGl0ZW0pID0+ICh7XG4gICAgICAgIC4uLml0ZW0sXG4gICAgICAgIGxlZnQ6IGNhcmV0UmVsYXRpdmVUb1ZpZXcubGVmdCAtIHNjcm9sbExlZnQgLSAobGVmdERpdiB8fCAwKSxcbiAgICAgICAgYm90dG9tOiB3aW5kb3cucGFyZW50LmlubmVySGVpZ2h0IC0gY2FyZXRSZWxhdGl2ZVRvVmlldy50b3AgKyAxOCxcbiAgICAgIH0pKTtcbiAgICAgIGlmIChjYXJldFJlbGF0aXZlVG9WaWV3LmJvdHRvbSAmJiBjYXJldFJlbGF0aXZlVG9WaWV3LmJvdHRvbSAhPT0gLTEpIHtcbiAgICAgICAgdGhpcy5jb29yZHMudXBkYXRlKChpdGVtKSA9PiAoe1xuICAgICAgICAgIC4uLml0ZW0sXG4gICAgICAgICAgYm90dG9tOiBjYXJldFJlbGF0aXZlVG9WaWV3LmJvdHRvbSxcbiAgICAgICAgfSkpO1xuICAgICAgfVxuICAgICAgdGhpcy5wb3NpdGlvbkVsZW1lbnQoKTtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBkb2MgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gICAgY29uc3Qgc2Nyb2xsTGVmdCA9ICh3aW5kb3cuc2Nyb2xsWCB8fCBkb2Muc2Nyb2xsTGVmdCkgLSAoZG9jLmNsaWVudExlZnQgfHwgMCk7XG4gICAgY29uc3Qgc2Nyb2xsVG9wID0gKHdpbmRvdy5zY3JvbGxYIHx8IGRvYy5zY3JvbGxUb3ApIC0gKGRvYy5jbGllbnRUb3AgfHwgMCk7XG4gICAgLy8gYm91bmRpbmcgcmVjdGFuZ2xlcyBhcmUgcmVsYXRpdmUgdG8gdmlldywgb2Zmc2V0cyBhcmUgcmVsYXRpdmUgdG8gY29udGFpbmVyP1xuICAgIGNvbnN0IGNhcmV0UmVsYXRpdmVUb1ZpZXcgPSBnZXRDb250ZW50RWRpdGFibGVDYXJldENvb3Jkcyh7IGlmcmFtZSwgcGFyZW50OiBudWxsIH0pO1xuXG4gICAgdGhpcy5jb29yZHMudXBkYXRlKChpdGVtKSA9PiAoe1xuICAgICAgLi4uaXRlbSxcbiAgICAgIHRvcDogY2FyZXRSZWxhdGl2ZVRvVmlldy50b3AgLSBzY3JvbGxUb3AgKyAxMCxcbiAgICAgIGxlZnQ6IGNhcmV0UmVsYXRpdmVUb1ZpZXcubGVmdCAtIHNjcm9sbExlZnQgLSAobGVmdERpdiB8fCAwKSxcbiAgICAgIGJvdHRvbTogY2FyZXRSZWxhdGl2ZVRvVmlldy5ib3R0b20sXG4gICAgfSkpO1xuICAgIHRoaXMucG9zaXRpb25FbGVtZW50KCk7XG4gIH1cblxuICBnZXQgQWN0aXZlSXRlbSgpIHtcbiAgICByZXR1cm4gdGhpcy5pdGVtcygpW3RoaXMuYWN0aXZlSW5kZXgoKV07XG4gIH1cblxuICBwcm90ZWN0ZWQgaGFuZGxlckNsaWNrKGV2ZW50OiBFdmVudCwgaW5kZXg6IG51bWJlcikge1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIHRoaXMuYWN0aXZlSW5kZXguc2V0KGluZGV4KTtcbiAgICBzZXQoZXZlbnQgYXMgS2V5Ym9hcmRFdmVudCwgJ2tleUNvZGUnLCBVdGlsc0tleUNvZGVDb25zdGFudC5FTlRFUik7XG4gICAgdGhpcy5wYXJlbnRIYW5kbGVyS2V5RG93bigpPy4oZXZlbnQsIHRoaXMubmF0aXZlUGFyZW50RWxlbWVudCgpKTtcbiAgfVxuXG4gIGFjdGl2YXRlTmV4dEl0ZW0oKSB7XG4gICAgdGhpcy5hY3RpdmVJbmRleC5zZXQodGhpcy5pdGVtcygpLmxlbmd0aCAtIDEgPiB0aGlzLmFjdGl2ZUluZGV4KCkgPyB0aGlzLmFjdGl2ZUluZGV4KCkgKyAxIDogdGhpcy5hY3RpdmVJbmRleCgpKTtcbiAgICB0aGlzLnNjcm9sbFRvQWN0aXZlKCk7XG4gIH1cblxuICBhY3RpdmF0ZVByZXZpb3VzSXRlbSgpIHtcbiAgICB0aGlzLmFjdGl2ZUluZGV4LnNldCh0aGlzLmFjdGl2ZUluZGV4KCkgPiAwID8gdGhpcy5hY3RpdmVJbmRleCgpIC0gMSA6IHRoaXMuYWN0aXZlSW5kZXgoKSk7XG4gICAgdGhpcy5zY3JvbGxUb0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBwb3NpdGlvbkVsZW1lbnQobGVmdDogbnVtYmVyID0gdGhpcy5jb29yZHMoKS5sZWZ0LCB0b3A6IG51bWJlciA9IHRoaXMuY29vcmRzKCkudG9wLCBkcm9wVXA6IGJvb2xlYW4gPSB0aGlzLmRyb3BVcCgpLCBib3R0b206IG51bWJlciA9IHRoaXMuY29vcmRzKCkuYm90dG9tIHx8IDApIHtcbiAgICBjb25zdCBlbCA9IHRoaXMuZWxlbWVudEVsKCk/Lm5hdGl2ZUVsZW1lbnQ7XG5cbiAgICB0b3AgKz0gZHJvcFVwID8gMCA6IHRoaXMub2Zmc2V0KCk7IC8vIHRvcCBvZiBsaXN0IGlzIG5leHQgbGluZVxuICAgIGVsLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBlbC5zdHlsZS5sZWZ0ID0gbGVmdCArICdweCc7XG4gICAgZWwuc3R5bGUudG9wID0gYm90dG9tICE9PSAtMSA/ICdhdXRvJyA6IHRvcCArICdweCc7XG4gICAgZWwuc3R5bGUuYm90dG9tID0gYm90dG9tID09PSAtMSA/ICdhdXRvJyA6IGJvdHRvbSArICdweCc7XG4gICAgdGhpcy5uYXRpdmVQYXJlbnRFbGVtZW50KCk/Lm5vcm1hbGl6ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRCbG9ja0N1cnNvckRpbWVuc2lvbnMobmF0aXZlUGFyZW50RWxlbWVudDogSFRNTElucHV0RWxlbWVudCkge1xuICAgIGNvbnN0IHBhcmVudFN0eWxlcyA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKG5hdGl2ZVBhcmVudEVsZW1lbnQpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGhlaWdodDogcGFyc2VGbG9hdChwYXJlbnRTdHlsZXMubGluZUhlaWdodCksXG4gICAgICB3aWR0aDogcGFyc2VGbG9hdChwYXJlbnRTdHlsZXMuZm9udFNpemUpLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgaGFuZGxlQWN0aXZlSXRlbShldmVudDogRXZlbnQsIGluZGV4OiBudW1iZXIpIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLmFjdGl2ZUluZGV4LnNldChpbmRleCk7XG4gIH1cblxuICBwcml2YXRlIHNjcm9sbFRvQWN0aXZlKCkge1xuICAgIGlmICghdGhpcy5pdGVtc0VsKCkgfHwgdGhpcy5pdGVtc0VsKCkubGVuZ3RoIDw9IHRoaXMuYWN0aXZlSW5kZXgoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLml0ZW1zRWwoKVt0aGlzLmFjdGl2ZUluZGV4KCldLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsSW50b1ZpZXcoKTtcbiAgfVxuXG4gIHNjcm9sbENvbnRlbnQoKSB7XG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5lbGVtZW50RWwoKTtcbiAgICAgIGlmIChlbGVtZW50ICYmIGVsZW1lbnQubmF0aXZlRWxlbWVudCkge1xuICAgICAgICBlbGVtZW50Lm5hdGl2ZUVsZW1lbnQuc2Nyb2xsVG9wID0gMDtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMub25EZXN0cm95Lm5leHQoKTtcbiAgICB0aGlzLm9uRGVzdHJveS5jb21wbGV0ZSgpO1xuICB9XG59XG4iLCI8ZGl2XG4gICNlbGVtZW50XG4gIGNsYXNzPVwibGlicy11aS1tZW50aW9uLWxpc3RcIlxuICBbc3R5bGUuekluZGV4XT1cInpJbmRleCgpXCJcbiAgW2NsYXNzLmhpZGRlbl09XCJoaWRkZW4oKVwiPlxuICBAZm9yIChpdGVtIG9mIGl0ZW1zKCk7IHRyYWNrIGl0ZW0pIHtcbiAgICA8ZGl2XG4gICAgICAjaXRlbVxuICAgICAgY2xhc3M9XCJsaWJzLXVpLW1lbnRpb24tbGlzdC1pdGVtXCJcbiAgICAgIFtjbGFzcy5saWJzLXVpLW1lbnRpb24tbGlzdC1pdGVtLWFjdGl2ZV09XCIkaW5kZXggPT09IGFjdGl2ZUluZGV4KClcIlxuICAgICAgKG1vdXNlZG93bik9XCJoYW5kbGVyQ2xpY2soJGV2ZW50LCAkaW5kZXgpXCJcbiAgICAgIChtb3VzZWVudGVyKT1cImhhbmRsZUFjdGl2ZUl0ZW0oJGV2ZW50LCAkaW5kZXgpXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwicHgtWzEycHhdIHB5LVs2cHhdIGZsZXggaXRlbXMtY2VudGVyXCI+XG4gICAgICAgIDxsaWJzX3VpLWNvbXBvbmVudHMtYXZhdGFyXG4gICAgICAgICAgW3NpemVdPVwiMjRcIlxuICAgICAgICAgIFtsaW5rQXZhdGFyXT1cIml0ZW0uYXZhdGFyXCJcbiAgICAgICAgICBbbGlua0F2YXRhckVycm9yXT1cImRlZmF1bHRBdmF0YXIoKVwiXG4gICAgICAgICAgW2dldExhc3RUZXh0QWZ0ZXJTcGFjZV09XCJ0cnVlXCJcbiAgICAgICAgICBbdGV4dEF2YXRhcl09XCJpdGVtLm5hbWVcIlxuICAgICAgICAgIFtpZEdlbkNvbG9yXT1cIml0ZW0uaWRcIiAvPlxuICAgICAgICA8bGlic191aS1jb21wb25lbnRzLXBvcG92ZXJcbiAgICAgICAgICBbY2xhc3NJbmNsdWRlXT1cIidsaWJzLXVpLWZvbnQtaDVyJ1wiXG4gICAgICAgICAgW3R5cGVdPVwiJ3RleHQnXCJcbiAgICAgICAgICBbaWdub3JlU2hvd1BvcG92ZXJdPVwidHJ1ZVwiXG4gICAgICAgICAgW2NvbmZpZ109XCJ7IHdpZHRoOiAyNTAgfVwiPlxuICAgICAgICAgIDwhLS0gLy8gdGEubSDhuqluIHNob3cgdG9vbHRpcCB2w6wgY2jGsGEgeOG7rSBsw70gxJFjIHbhu4sgdHLDrSAtLT5cbiAgICAgICAgICB7eyBpdGVtLm5hbWUgKyAnICgnICsgaXRlbS51c2VybmFtZSArICcpJyB9fVxuICAgICAgICA8L2xpYnNfdWktY29tcG9uZW50cy1wb3BvdmVyPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIH1cbjwvZGl2PlxuIl19
|