@flogeez/angular-tiptap-editor 3.1.3 → 3.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +2 -2
  3. package/esm2022/flogeez-angular-tiptap-editor.mjs +5 -0
  4. package/esm2022/lib/ate-editor.provider.mjs +38 -0
  5. package/esm2022/lib/components/bubble-menus/base/ate-base-bubble-menu.mjs +207 -0
  6. package/esm2022/lib/components/bubble-menus/base/ate-base-sub-bubble-menu.mjs +137 -0
  7. package/esm2022/lib/components/bubble-menus/color/ate-color-bubble-menu.component.mjs +365 -0
  8. package/esm2022/lib/components/bubble-menus/image/ate-image-bubble-menu.component.mjs +309 -0
  9. package/esm2022/lib/components/bubble-menus/link/ate-link-bubble-menu.component.mjs +247 -0
  10. package/esm2022/lib/components/bubble-menus/table/ate-cell-bubble-menu.component.mjs +126 -0
  11. package/esm2022/lib/components/bubble-menus/table/ate-table-bubble-menu.component.mjs +271 -0
  12. package/esm2022/lib/components/bubble-menus/text/ate-bubble-menu.component.mjs +272 -0
  13. package/esm2022/lib/components/color-picker/ate-color-picker.component.mjs +123 -0
  14. package/esm2022/lib/components/edit-toggle/ate-edit-toggle.component.mjs +42 -0
  15. package/esm2022/lib/components/editor/angular-tiptap-editor.component.mjs +1032 -0
  16. package/esm2022/lib/components/editor/ate-block-controls.component.mjs +256 -0
  17. package/esm2022/lib/components/slash-commands/ate-slash-commands.component.mjs +328 -0
  18. package/esm2022/lib/components/toolbar/ate-toolbar.component.mjs +531 -0
  19. package/esm2022/lib/components/ui/ate-button.component.mjs +91 -0
  20. package/esm2022/lib/components/ui/ate-separator.component.mjs +11 -0
  21. package/esm2022/lib/config/ate-editor.config.mjs +133 -0
  22. package/esm2022/lib/config/ate-global-config.token.mjs +6 -0
  23. package/esm2022/lib/config/ate-slash-commands.config.mjs +130 -0
  24. package/esm2022/lib/directives/ate-noop-value-accessor.directive.mjs +40 -0
  25. package/esm2022/lib/directives/ate-tooltip.directive.mjs +138 -0
  26. package/esm2022/lib/extensions/ate-block-controls.extension.mjs +156 -0
  27. package/esm2022/lib/extensions/ate-link-click-behavior.extension.mjs +32 -0
  28. package/esm2022/lib/extensions/ate-resizable-image.extension.mjs +277 -0
  29. package/esm2022/lib/extensions/ate-table.extension.mjs +27 -0
  30. package/esm2022/lib/extensions/ate-tiptap-state.extension.mjs +85 -0
  31. package/esm2022/lib/extensions/ate-upload-progress.extension.mjs +195 -0
  32. package/esm2022/lib/extensions/calculators/ate-discovery.calculator.mjs +62 -0
  33. package/esm2022/lib/extensions/calculators/ate-image.calculator.mjs +8 -0
  34. package/esm2022/lib/extensions/calculators/ate-marks.calculator.mjs +75 -0
  35. package/esm2022/lib/extensions/calculators/ate-selection.calculator.mjs +35 -0
  36. package/esm2022/lib/extensions/calculators/ate-structure.calculator.mjs +34 -0
  37. package/esm2022/lib/extensions/calculators/ate-table.calculator.mjs +38 -0
  38. package/esm2022/lib/models/ate-bubble-menu.model.mjs +53 -0
  39. package/esm2022/lib/models/ate-editor-config.model.mjs +2 -0
  40. package/esm2022/lib/models/ate-editor-state.model.mjs +90 -0
  41. package/esm2022/lib/models/ate-image.model.mjs +2 -0
  42. package/esm2022/lib/models/ate-slash-command.model.mjs +2 -0
  43. package/esm2022/lib/models/ate-toolbar.model.mjs +35 -0
  44. package/esm2022/lib/node-view/ate-angular-node-view.mjs +97 -0
  45. package/esm2022/lib/node-view/ate-injector.registry.mjs +16 -0
  46. package/esm2022/lib/node-view/ate-node-view.factory.mjs +125 -0
  47. package/esm2022/lib/node-view/ate-node-view.models.mjs +2 -0
  48. package/esm2022/lib/node-view/ate-node-view.renderer.mjs +154 -0
  49. package/esm2022/lib/node-view/ate-register-angular-component.mjs +49 -0
  50. package/esm2022/lib/services/ate-color-picker.service.mjs +194 -0
  51. package/esm2022/lib/services/ate-editor-commands.service.mjs +507 -0
  52. package/esm2022/lib/services/ate-export.service.mjs +71 -0
  53. package/esm2022/lib/services/ate-i18n.service.mjs +449 -0
  54. package/esm2022/lib/services/ate-image.service.mjs +459 -0
  55. package/esm2022/lib/services/ate-link.service.mjs +99 -0
  56. package/esm2022/lib/utils/ate-color.utils.mjs +60 -0
  57. package/esm2022/lib/utils/ate-markdown.utils.mjs +179 -0
  58. package/esm2022/public-api.mjs +41 -0
  59. package/fesm2022/flogeez-angular-tiptap-editor.mjs +627 -354
  60. package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
  61. package/index.d.ts +3 -1734
  62. package/lib/ate-editor.provider.d.ts +21 -0
  63. package/lib/components/bubble-menus/base/ate-base-bubble-menu.d.ts +71 -0
  64. package/lib/components/bubble-menus/base/ate-base-sub-bubble-menu.d.ts +60 -0
  65. package/lib/components/bubble-menus/color/ate-color-bubble-menu.component.d.ts +77 -0
  66. package/lib/components/bubble-menus/image/ate-image-bubble-menu.component.d.ts +49 -0
  67. package/lib/components/bubble-menus/link/ate-link-bubble-menu.component.d.ts +55 -0
  68. package/lib/components/bubble-menus/table/ate-cell-bubble-menu.component.d.ts +16 -0
  69. package/lib/components/bubble-menus/table/ate-table-bubble-menu.component.d.ts +25 -0
  70. package/lib/components/bubble-menus/text/ate-bubble-menu.component.d.ts +53 -0
  71. package/lib/components/color-picker/ate-color-picker.component.d.ts +54 -0
  72. package/lib/components/edit-toggle/ate-edit-toggle.component.d.ts +13 -0
  73. package/lib/components/editor/angular-tiptap-editor.component.d.ts +242 -0
  74. package/lib/components/editor/ate-block-controls.component.d.ts +44 -0
  75. package/lib/components/slash-commands/ate-slash-commands.component.d.ts +34 -0
  76. package/lib/components/toolbar/ate-toolbar.component.d.ts +47 -0
  77. package/lib/components/ui/ate-button.component.d.ts +25 -0
  78. package/lib/components/ui/ate-separator.component.d.ts +5 -0
  79. package/lib/config/ate-editor.config.d.ts +19 -0
  80. package/lib/config/ate-global-config.token.d.ts +6 -0
  81. package/lib/config/ate-slash-commands.config.d.ts +41 -0
  82. package/lib/directives/ate-noop-value-accessor.directive.d.ts +13 -0
  83. package/lib/directives/ate-tooltip.directive.d.ts +30 -0
  84. package/lib/extensions/ate-block-controls.extension.d.ts +10 -0
  85. package/lib/extensions/ate-link-click-behavior.extension.d.ts +2 -0
  86. package/lib/extensions/ate-resizable-image.extension.d.ts +27 -0
  87. package/lib/extensions/ate-table.extension.d.ts +2 -0
  88. package/lib/extensions/ate-tiptap-state.extension.d.ts +7 -0
  89. package/lib/extensions/ate-upload-progress.extension.d.ts +7 -0
  90. package/lib/extensions/calculators/ate-discovery.calculator.d.ts +7 -0
  91. package/lib/extensions/calculators/ate-image.calculator.d.ts +2 -0
  92. package/lib/extensions/calculators/ate-marks.calculator.d.ts +2 -0
  93. package/lib/extensions/calculators/ate-selection.calculator.d.ts +2 -0
  94. package/lib/extensions/calculators/ate-structure.calculator.d.ts +2 -0
  95. package/lib/extensions/calculators/ate-table.calculator.d.ts +2 -0
  96. package/lib/models/ate-bubble-menu.model.d.ts +33 -0
  97. package/lib/models/ate-editor-config.model.d.ts +113 -0
  98. package/lib/models/ate-editor-state.model.d.ts +109 -0
  99. package/lib/models/ate-image.model.d.ts +104 -0
  100. package/lib/models/ate-slash-command.model.d.ts +17 -0
  101. package/lib/models/ate-toolbar.model.d.ts +18 -0
  102. package/lib/node-view/ate-angular-node-view.d.ts +115 -0
  103. package/lib/node-view/ate-injector.registry.d.ts +3 -0
  104. package/lib/node-view/ate-node-view.factory.d.ts +10 -0
  105. package/lib/node-view/ate-node-view.models.d.ts +138 -0
  106. package/lib/node-view/ate-node-view.renderer.d.ts +23 -0
  107. package/lib/node-view/ate-register-angular-component.d.ts +35 -0
  108. package/lib/services/ate-color-picker.service.d.ts +65 -0
  109. package/lib/services/ate-editor-commands.service.d.ts +89 -0
  110. package/lib/services/ate-export.service.d.ts +27 -0
  111. package/lib/services/ate-i18n.service.d.ts +432 -0
  112. package/lib/services/ate-image.service.d.ts +82 -0
  113. package/lib/services/ate-link.service.d.ts +42 -0
  114. package/lib/utils/ate-color.utils.d.ts +12 -0
  115. package/lib/utils/ate-markdown.utils.d.ts +4 -0
  116. package/package.json +3 -1
  117. package/public-api.d.ts +32 -0
@@ -0,0 +1,256 @@
1
+ import { Component, input, viewChild, effect, signal, inject, ChangeDetectionStrategy, } from "@angular/core";
2
+ import tippy, { sticky } from "tippy.js";
3
+ import { AteI18nService } from "../../services/ate-i18n.service";
4
+ import { AteTooltipDirective } from "../../directives/ate-tooltip.directive";
5
+ import * as i0 from "@angular/core";
6
+ /**
7
+ * Component providing Notion-like block controls (Plus button and Drag Handle).
8
+ */
9
+ export class AteBlockControlsComponent {
10
+ constructor() {
11
+ this.i18n = inject(AteI18nService);
12
+ this.editor = input.required();
13
+ this.hoveredData = input(null);
14
+ this.menuRef = viewChild.required("menuRef");
15
+ this.isInteracting = signal(false);
16
+ this.lastValidData = null;
17
+ this.lastValidRect = null;
18
+ this.tippyInstance = null;
19
+ this.updateTimeout = null;
20
+ effect(() => {
21
+ const data = this.hoveredData();
22
+ const interacting = this.isInteracting();
23
+ if (data) {
24
+ this.lastValidData = data;
25
+ this.lastValidRect = data.element.getBoundingClientRect();
26
+ }
27
+ this.updateMenu(!!data || interacting);
28
+ });
29
+ }
30
+ ngAfterViewInit() {
31
+ this.initTippy();
32
+ }
33
+ ngOnDestroy() {
34
+ if (this.updateTimeout) {
35
+ window.clearTimeout(this.updateTimeout);
36
+ }
37
+ if (this.tippyInstance) {
38
+ this.tippyInstance.destroy();
39
+ this.tippyInstance = null;
40
+ }
41
+ }
42
+ initTippy() {
43
+ const nativeElement = this.menuRef().nativeElement;
44
+ if (!nativeElement) {
45
+ return;
46
+ }
47
+ this.tippyInstance = tippy(document.body, {
48
+ content: nativeElement,
49
+ trigger: "manual",
50
+ placement: "left",
51
+ theme: "ate-block-controls",
52
+ appendTo: () => this.editor()?.options?.element || document.body,
53
+ interactive: true,
54
+ hideOnClick: false,
55
+ arrow: false,
56
+ offset: [0, 8],
57
+ zIndex: 99,
58
+ plugins: [sticky],
59
+ sticky: "reference",
60
+ moveTransition: "transform 0.2s ease-out",
61
+ getReferenceClientRect: () => this.getSelectionRect(),
62
+ popperOptions: {
63
+ modifiers: [
64
+ {
65
+ name: "preventOverflow",
66
+ options: {
67
+ boundary: this.editor()?.options?.element || document.body,
68
+ padding: 8,
69
+ },
70
+ },
71
+ ],
72
+ },
73
+ });
74
+ }
75
+ updateMenu(show) {
76
+ if (this.updateTimeout) {
77
+ window.clearTimeout(this.updateTimeout);
78
+ }
79
+ const delay = show ? 0 : 400;
80
+ this.updateTimeout = window.setTimeout(() => {
81
+ if (show) {
82
+ this.showTippy();
83
+ }
84
+ else {
85
+ this.hideTippy();
86
+ }
87
+ }, delay);
88
+ }
89
+ showTippy() {
90
+ if (this.tippyInstance) {
91
+ this.tippyInstance.setProps({
92
+ getReferenceClientRect: () => this.getSelectionRect(),
93
+ });
94
+ this.tippyInstance.show();
95
+ }
96
+ }
97
+ hideTippy() {
98
+ if (this.tippyInstance) {
99
+ this.tippyInstance.hide();
100
+ }
101
+ }
102
+ getSelectionRect() {
103
+ const data = this.hoveredData();
104
+ if (data && data.element) {
105
+ return data.element.getBoundingClientRect();
106
+ }
107
+ return this.lastValidRect || new DOMRect(-9999, -9999, 0, 0);
108
+ }
109
+ onMouseEnter() {
110
+ this.isInteracting.set(true);
111
+ }
112
+ onMouseLeave() {
113
+ this.isInteracting.set(false);
114
+ }
115
+ onContainerMouseDown(event) {
116
+ if (event.target === event.currentTarget) {
117
+ event.preventDefault();
118
+ }
119
+ }
120
+ onButtonMouseDown(event) {
121
+ event.preventDefault();
122
+ }
123
+ /**
124
+ * Selection strategy to avoid partial node dragging (ghost table issue).
125
+ */
126
+ onDragHandleMouseDown(event) {
127
+ event.stopPropagation();
128
+ const ed = this.editor();
129
+ const data = this.hoveredData() || this.lastValidData;
130
+ if (ed && data) {
131
+ // Force whole-node selection. This is crucial for atomic nodes like tables and images.
132
+ ed.commands.setNodeSelection(data.pos);
133
+ }
134
+ }
135
+ addBlock(event) {
136
+ event.stopPropagation();
137
+ const ed = this.editor();
138
+ const data = this.hoveredData() || this.lastValidData;
139
+ if (!ed || !data) {
140
+ return;
141
+ }
142
+ const { pos, node } = data;
143
+ if (node.content.size === 0) {
144
+ ed.chain()
145
+ .focus()
146
+ .setTextSelection(pos + 1)
147
+ .insertContent("/")
148
+ .run();
149
+ }
150
+ else {
151
+ const nextPos = pos + node.nodeSize;
152
+ ed.chain()
153
+ .focus()
154
+ .insertContentAt(nextPos, { type: "paragraph", content: [{ type: "text", text: "/" }] })
155
+ .setTextSelection(nextPos + 2)
156
+ .run();
157
+ }
158
+ this.isInteracting.set(false);
159
+ this.hideTippy();
160
+ }
161
+ onDragStart(event) {
162
+ const ed = this.editor();
163
+ const data = this.hoveredData() || this.lastValidData;
164
+ if (!ed || !data || !event.dataTransfer) {
165
+ return;
166
+ }
167
+ const { element, pos } = data;
168
+ const view = ed.view;
169
+ // 1. Force the editor to focus and select the ENTIRE node
170
+ view.focus();
171
+ ed.commands.setNodeSelection(pos);
172
+ // 2. Browser Drag Image & metadata
173
+ event.dataTransfer.setDragImage(element, 0, 10);
174
+ event.dataTransfer.effectAllowed = "move";
175
+ event.dataTransfer.setData("text/plain", "");
176
+ // 3. PRO-HACK: Indicate this is a move of the current selection (the whole node)
177
+ view.dragging = {
178
+ slice: ed.state.selection.content(),
179
+ move: true,
180
+ };
181
+ // 4. Dispatch virtual dragstart
182
+ const pmEvent = new DragEvent("dragstart", {
183
+ dataTransfer: event.dataTransfer,
184
+ bubbles: true,
185
+ cancelable: true,
186
+ });
187
+ element.dispatchEvent(pmEvent);
188
+ // 5. Cleanup UI
189
+ setTimeout(() => {
190
+ this.hideTippy();
191
+ this.isInteracting.set(false);
192
+ }, 0);
193
+ }
194
+ onDragEnd() {
195
+ this.isInteracting.set(false);
196
+ }
197
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteBlockControlsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
198
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "18.2.14", type: AteBlockControlsComponent, isStandalone: true, selector: "ate-block-controls", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, hoveredData: { classPropertyName: "hoveredData", publicName: "hoveredData", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "menuRef", first: true, predicate: ["menuRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
199
+ <div
200
+ #menuRef
201
+ class="ate-block-controls"
202
+ (mouseenter)="onMouseEnter()"
203
+ (mouseleave)="onMouseLeave()"
204
+ (mousedown)="onContainerMouseDown($event)">
205
+ <button
206
+ class="ate-control-btn ate-block-add"
207
+ (mousedown)="onButtonMouseDown($event)"
208
+ (click)="addBlock($event)"
209
+ [ateTooltip]="i18n.editor().blockAdd"
210
+ ateTooltipPlacement="top">
211
+ <span class="material-symbols-outlined">add</span>
212
+ </button>
213
+ <div
214
+ class="ate-control-btn ate-block-drag"
215
+ draggable="true"
216
+ (mousedown)="onDragHandleMouseDown($event)"
217
+ (dragstart)="onDragStart($event)"
218
+ (dragend)="onDragEnd()"
219
+ [ateTooltip]="i18n.editor().blockDrag"
220
+ ateTooltipPlacement="top">
221
+ <span class="material-symbols-outlined">drag_indicator</span>
222
+ </div>
223
+ </div>
224
+ `, isInline: true, styles: [".ate-block-controls{display:flex;align-items:center;gap:2px;padding:4px;pointer-events:auto;will-change:transform}.ate-control-btn{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:4px;border:none;background:transparent;color:var(--ate-text-secondary);cursor:pointer;transition:all .15s ease}.ate-control-btn:hover{background:var(--ate-surface-tertiary);color:var(--ate-text)}.ate-control-btn .material-symbols-outlined{font-size:18px}@media (max-width: 768px){:host{display:none!important}}\n"], dependencies: [{ kind: "directive", type: AteTooltipDirective, selector: "[ateTooltip]", inputs: ["ateTooltip", "ateTooltipPlacement", "ateTooltipDelay", "ateTooltipDisabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
225
+ }
226
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteBlockControlsComponent, decorators: [{
227
+ type: Component,
228
+ args: [{ selector: "ate-block-controls", standalone: true, imports: [AteTooltipDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: `
229
+ <div
230
+ #menuRef
231
+ class="ate-block-controls"
232
+ (mouseenter)="onMouseEnter()"
233
+ (mouseleave)="onMouseLeave()"
234
+ (mousedown)="onContainerMouseDown($event)">
235
+ <button
236
+ class="ate-control-btn ate-block-add"
237
+ (mousedown)="onButtonMouseDown($event)"
238
+ (click)="addBlock($event)"
239
+ [ateTooltip]="i18n.editor().blockAdd"
240
+ ateTooltipPlacement="top">
241
+ <span class="material-symbols-outlined">add</span>
242
+ </button>
243
+ <div
244
+ class="ate-control-btn ate-block-drag"
245
+ draggable="true"
246
+ (mousedown)="onDragHandleMouseDown($event)"
247
+ (dragstart)="onDragStart($event)"
248
+ (dragend)="onDragEnd()"
249
+ [ateTooltip]="i18n.editor().blockDrag"
250
+ ateTooltipPlacement="top">
251
+ <span class="material-symbols-outlined">drag_indicator</span>
252
+ </div>
253
+ </div>
254
+ `, styles: [".ate-block-controls{display:flex;align-items:center;gap:2px;padding:4px;pointer-events:auto;will-change:transform}.ate-control-btn{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:4px;border:none;background:transparent;color:var(--ate-text-secondary);cursor:pointer;transition:all .15s ease}.ate-control-btn:hover{background:var(--ate-surface-tertiary);color:var(--ate-text)}.ate-control-btn .material-symbols-outlined{font-size:18px}@media (max-width: 768px){:host{display:none!important}}\n"] }]
255
+ }], ctorParameters: () => [] });
256
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRlLWJsb2NrLWNvbnRyb2xzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItdGlwdGFwLWVkaXRvci9zcmMvbGliL2NvbXBvbmVudHMvZWRpdG9yL2F0ZS1ibG9jay1jb250cm9scy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBQ0wsU0FBUyxFQUdULE1BQU0sRUFDTixNQUFNLEVBQ04sTUFBTSxFQUNOLHVCQUF1QixHQUV4QixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEtBQUssRUFBRSxFQUE2QixNQUFNLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFHcEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHdDQUF3QyxDQUFDOztBQUU3RTs7R0FFRztBQTJFSCxNQUFNLE9BQU8seUJBQXlCO0lBY3BDO1FBYm1CLFNBQUksR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUM7UUFFakQsV0FBTSxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQVUsQ0FBQztRQUNsQyxnQkFBVyxHQUFHLEtBQUssQ0FBNkQsSUFBSSxDQUFDLENBQUM7UUFFdEYsWUFBTyxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQTZCLFNBQVMsQ0FBQyxDQUFDO1FBRTFELGtCQUFhLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2hDLGtCQUFhLEdBQStELElBQUksQ0FBQztRQUNqRixrQkFBYSxHQUFtQixJQUFJLENBQUM7UUFDckMsa0JBQWEsR0FBeUIsSUFBSSxDQUFDO1FBQzNDLGtCQUFhLEdBQWtCLElBQUksQ0FBQztRQUcxQyxNQUFNLENBQUMsR0FBRyxFQUFFO1lBQ1YsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFD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Q0FBQyxDQUFDO1FBRTdDLGlGQUFpRjtRQUNoRixJQUF5QyxDQUFDLFFBQVEsR0FBRztZQUNwRCxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFO1lBQ25DLElBQUksRUFBRSxJQUFJO1NBQ1gsQ0FBQztRQUVGLGdDQUFnQztRQUNoQyxNQUFNLE9BQU8sR0FBRyxJQUFJLFNBQVMsQ0FBQyxXQUFXLEVBQUU7WUFDekMsWUFBWSxFQUFFLEtBQUssQ0FBQyxZQUFZO1lBQ2hDLE9BQU8sRUFBRSxJQUFJO1lBQ2IsVUFBVSxFQUFFLElBQUk7U0FDakIsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUUvQixnQkFBZ0I7UUFDaEIsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUNkLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNqQixJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNoQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDUixDQUFDO0lBRUQsU0FBUztRQUNQLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLENBQUM7K0dBdk5VLHlCQUF5QjttR0FBekIseUJBQXlCLGtkQXJFMUI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMEJULGltQkE1QlMsbUJBQW1COzs0RkF1RWxCLHlCQUF5QjtrQkExRXJDLFNBQVM7K0JBQ0Usb0JBQW9CLGNBQ2xCLElBQUksV0FDUCxDQUFDLG1CQUFtQixDQUFDLG1CQUNiLHVCQUF1QixDQUFDLE1BQU0sWUFDckM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMEJUIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBpbnB1dCxcbiAgdmlld0NoaWxkLFxuICBFbGVtZW50UmVmLFxuICBPbkRlc3Ryb3ksXG4gIGVmZmVjdCxcbiAgc2lnbmFsLFxuICBpbmplY3QsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBBZnRlclZpZXdJbml0LFxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHRpcHB5LCB7IEluc3RhbmNlIGFzIFRpcHB5SW5zdGFuY2UsIHN0aWNreSB9IGZyb20gXCJ0aXBweS5qc1wiO1xuaW1wb3J0IHsgRWRpdG9yIH0gZnJvbSBcIkB0aXB0YXAvY29yZVwiO1xuaW1wb3J0IHsgTm9kZSBhcyBQTU5vZGUgfSBmcm9tIFwiQHRpcHRhcC9wbS9tb2RlbFwiO1xuaW1wb3J0IHsgQXRlSTE4blNlcnZpY2UgfSBmcm9tIFwiLi4vLi4vc2VydmljZXMvYXRlLWkxOG4uc2VydmljZVwiO1xuaW1wb3J0IHsgQXRlVG9vbHRpcERpcmVjdGl2ZSB9IGZyb20gXCIuLi8uLi9kaXJlY3RpdmVzL2F0ZS10b29sdGlwLmRpcmVjdGl2ZVwiO1xuXG4vKipcbiAqIENvbXBvbmVudCBwcm92aWRpbmcgTm90aW9uLWxpa2UgYmxvY2sgY29udHJvbHMgKFBsdXMgYnV0dG9uIGFuZCBEcmFnIEhhbmRsZSkuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJhdGUtYmxvY2stY29udHJvbHNcIixcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0F0ZVRvb2x0aXBEaXJlY3RpdmVdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2XG4gICAgICAjbWVudVJlZlxuICAgICAgY2xhc3M9XCJhdGUtYmxvY2stY29udHJvbHNcIlxuICAgICAgKG1vdXNlZW50ZXIpPVwib25Nb3VzZUVudGVyKClcIlxuICAgICAgKG1vdXNlbGVhdmUpPVwib25Nb3VzZUxlYXZlKClcIlxuICAgICAgKG1vdXNlZG93bik9XCJvbkNvbnRhaW5lck1vdXNlRG93bigkZXZlbnQpXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIGNsYXNzPVwiYXRlLWNvbnRyb2wtYnRuIGF0ZS1ibG9jay1hZGRcIlxuICAgICAgICAobW91c2Vkb3duKT1cIm9uQnV0dG9uTW91c2VEb3duKCRldmVudClcIlxuICAgICAgICAoY2xpY2spPVwiYWRkQmxvY2soJGV2ZW50KVwiXG4gICAgICAgIFthdGVUb29sdGlwXT1cImkxOG4uZWRpdG9yKCkuYmxvY2tBZGRcIlxuICAgICAgICBhdGVUb29sdGlwUGxhY2VtZW50PVwidG9wXCI+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwibWF0ZXJpYWwtc3ltYm9scy1vdXRsaW5lZFwiPmFkZDwvc3Bhbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cImF0ZS1jb250cm9sLWJ0biBhdGUtYmxvY2stZHJhZ1wiXG4gICAgICAgIGRyYWdnYWJsZT1cInRydWVcIlxuICAgICAgICAobW91c2Vkb3duKT1cIm9uRHJhZ0hhbmRsZU1vdXNlRG93bigkZXZlbnQpXCJcbiAgICAgICAgKGRyYWdzdGFydCk9XCJvbkRyYWdTdGFydCgkZXZlbnQpXCJcbiAgICAgICAgKGRyYWdlbmQpPVwib25EcmFnRW5kKClcIlxuICAgICAgICBbYXRlVG9vbHRpcF09XCJpMThuLmVkaXRvcigpLmJsb2NrRHJhZ1wiXG4gICAgICAgIGF0ZVRvb2x0aXBQbGFjZW1lbnQ9XCJ0b3BcIj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJtYXRlcmlhbC1zeW1ib2xzLW91dGxpbmVkXCI+ZHJhZ19pbmRpY2F0b3I8L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVzOiBbXG4gICAgYFxuICAgICAgLmF0ZS1ibG9jay1jb250cm9scyB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICAgIGdhcDogMnB4O1xuICAgICAgICBwYWRkaW5nOiA0cHg7XG4gICAgICAgIHBvaW50ZXItZXZlbnRzOiBhdXRvO1xuICAgICAgICB3aWxsLWNoYW5nZTogdHJhbnNmb3JtO1xuICAgICAgfVxuXG4gICAgICAuYXRlLWNvbnRyb2wtYnRuIHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gICAgICAgIHdpZHRoOiAyNHB4O1xuICAgICAgICBoZWlnaHQ6IDI0cHg7XG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDRweDtcbiAgICAgICAgYm9yZGVyOiBub25lO1xuICAgICAgICBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDtcbiAgICAgICAgY29sb3I6IHZhcigtLWF0ZS10ZXh0LXNlY29uZGFyeSk7XG4gICAgICAgIGN1cnNvcjogcG9pbnRlcjtcbiAgICAgICAgdHJhbnNpdGlvbjogYWxsIDAuMTVzIGVhc2U7XG4gICAgICB9XG5cbiAgICAgIC5hdGUtY29udHJvbC1idG46aG92ZXIge1xuICAgICAgICBiYWNrZ3JvdW5kOiB2YXIoLS1hdGUtc3VyZmFjZS10ZXJ0aWFyeSk7XG4gICAgICAgIGNvbG9yOiB2YXIoLS1hdGUtdGV4dCk7XG4gICAgICB9XG5cbiAgICAgIC5hdGUtY29udHJvbC1idG4gLm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWQge1xuICAgICAgICBmb250LXNpemU6IDE4cHg7XG4gICAgICB9XG5cbiAgICAgIEBtZWRpYSAobWF4LXdpZHRoOiA3NjhweCkge1xuICAgICAgICA6aG9zdCB7XG4gICAgICAgICAgZGlzcGxheTogbm9uZSAhaW1wb3J0YW50O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgYCxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgQXRlQmxvY2tDb250cm9sc0NvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG4gIHByb3RlY3RlZCByZWFkb25seSBpMThuID0gaW5qZWN0KEF0ZUkxOG5TZXJ2aWNlKTtcblxuICBlZGl0b3IgPSBpbnB1dC5yZXF1aXJlZDxFZGl0b3I+KCk7XG4gIGhvdmVyZWREYXRhID0gaW5wdXQ8eyBub2RlOiBQTU5vZGU7IGVsZW1lbnQ6IEhUTUxFbGVtZW50OyBwb3M6IG51bWJlciB9IHwgbnVsbD4obnVsbCk7XG5cbiAgbWVudVJlZiA9IHZpZXdDaGlsZC5yZXF1aXJlZDxFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50Pj4oXCJtZW51UmVmXCIpO1xuXG4gIHByb3RlY3RlZCBpc0ludGVyYWN0aW5nID0gc2lnbmFsKGZhbHNlKTtcbiAgcHJpdmF0ZSBsYXN0VmFsaWREYXRhOiB7IG5vZGU6IFBNTm9kZTsgZWxlbWVudDogSFRNTEVsZW1lbnQ7IHBvczogbnVtYmVyIH0gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBsYXN0VmFsaWRSZWN0OiBET01SZWN0IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgdGlwcHlJbnN0YW5jZTogVGlwcHlJbnN0YW5jZSB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHVwZGF0ZVRpbWVvdXQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIGVmZmVjdCgoKSA9PiB7XG4gICAgICBjb25zdCBkYXRhID0gdGhpcy5ob3ZlcmVkRGF0YSgpO1xuICAgICAgY29uc3QgaW50ZXJhY3RpbmcgPSB0aGlzLmlzSW50ZXJhY3RpbmcoKTtcblxuICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgdGhpcy5sYXN0VmFsaWREYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5sYXN0VmFsaWRSZWN0ID0gZGF0YS5lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnVwZGF0ZU1lbnUoISFkYXRhIHx8IGludGVyYWN0aW5nKTtcbiAgICB9KTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLmluaXRUaXBweSgpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgaWYgKHRoaXMudXBkYXRlVGltZW91dCkge1xuICAgICAgd2luZG93LmNsZWFyVGltZW91dCh0aGlzLnVwZGF0ZVRpbWVvdXQpO1xuICAgIH1cbiAgICBpZiAodGhpcy50aXBweUluc3RhbmNlKSB7XG4gICAgICB0aGlzLnRpcHB5SW5zdGFuY2UuZGVzdHJveSgpO1xuICAgICAgdGhpcy50aXBweUluc3RhbmNlID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGluaXRUaXBweSgpIHtcbiAgICBjb25zdCBuYXRpdmVFbGVtZW50ID0gdGhpcy5tZW51UmVmKCkubmF0aXZlRWxlbWVudDtcbiAgICBpZiAoIW5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnRpcHB5SW5zdGFuY2UgPSB0aXBweShkb2N1bWVudC5ib2R5LCB7XG4gICAgICBjb250ZW50OiBuYXRpdmVFbGVtZW50LFxuICAgICAgdHJpZ2dlcjogXCJtYW51YWxcIixcbiAgICAgIHBsYWNlbWVudDogXCJsZWZ0XCIsXG4gICAgICB0aGVtZTogXCJhdGUtYmxvY2stY29udHJvbHNcIixcbiAgICAgIGFwcGVuZFRvOiAoKSA9PiAodGhpcy5lZGl0b3IoKT8ub3B0aW9ucz8uZWxlbWVudCBhcyBIVE1MRWxlbWVudCkgfHwgZG9jdW1lbnQuYm9keSxcbiAgICAgIGludGVyYWN0aXZlOiB0cnVlLFxuICAgICAgaGlkZU9uQ2xpY2s6IGZhbHNlLFxuICAgICAgYXJyb3c6IGZhbHNlLFxuICAgICAgb2Zmc2V0OiBbMCwgOF0sXG4gICAgICB6SW5kZXg6IDk5LFxuICAgICAgcGx1Z2luczogW3N0aWNreV0sXG4gICAgICBzdGlja3k6IFwicmVmZXJlbmNlXCIsXG4gICAgICBtb3ZlVHJhbnNpdGlvbjogXCJ0cmFuc2Zvcm0gMC4ycyBlYXNlLW91dFwiLFxuICAgICAgZ2V0UmVmZXJlbmNlQ2xpZW50UmVjdDogKCkgPT4gdGhpcy5nZXRTZWxlY3Rpb25SZWN0KCksXG4gICAgICBwb3BwZXJPcHRpb25zOiB7XG4gICAgICAgIG1vZGlmaWVyczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6IFwicHJldmVudE92ZXJmbG93XCIsXG4gICAgICAgICAgICBvcHRpb25zOiB7XG4gICAgICAgICAgICAgIGJvdW5kYXJ5OiAodGhpcy5lZGl0b3IoKT8ub3B0aW9ucz8uZWxlbWVudCBhcyBIVE1MRWxlbWVudCkgfHwgZG9jdW1lbnQuYm9keSxcbiAgICAgICAgICAgICAgcGFkZGluZzogOCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZU1lbnUoc2hvdzogYm9vbGVhbikge1xuICAgIGlmICh0aGlzLnVwZGF0ZVRpbWVvdXQpIHtcbiAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGhpcy51cGRhdGVUaW1lb3V0KTtcbiAgICB9XG4gICAgY29uc3QgZGVsYXkgPSBzaG93ID8gMCA6IDQwMDtcbiAgICB0aGlzLnVwZGF0ZVRpbWVvdXQgPSB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBpZiAoc2hvdykge1xuICAgICAgICB0aGlzLnNob3dUaXBweSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5oaWRlVGlwcHkoKTtcbiAgICAgIH1cbiAgICB9LCBkZWxheSk7XG4gIH1cblxuICBwcml2YXRlIHNob3dUaXBweSgpIHtcbiAgICBpZiAodGhpcy50aXBweUluc3RhbmNlKSB7XG4gICAgICB0aGlzLnRpcHB5SW5zdGFuY2Uuc2V0UHJvcHMoe1xuICAgICAgICBnZXRSZWZlcmVuY2VDbGllbnRSZWN0OiAoKSA9PiB0aGlzLmdldFNlbGVjdGlvblJlY3QoKSxcbiAgICAgIH0pO1xuICAgICAgdGhpcy50aXBweUluc3RhbmNlLnNob3coKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGhpZGVUaXBweSgpIHtcbiAgICBpZiAodGhpcy50aXBweUluc3RhbmNlKSB7XG4gICAgICB0aGlzLnRpcHB5SW5zdGFuY2UuaGlkZSgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0U2VsZWN0aW9uUmVjdCgpOiBET01SZWN0IHtcbiAgICBjb25zdCBkYXRhID0gdGhpcy5ob3ZlcmVkRGF0YSgpO1xuICAgIGlmIChkYXRhICYmIGRhdGEuZWxlbWVudCkge1xuICAgICAgcmV0dXJuIGRhdGEuZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMubGFzdFZhbGlkUmVjdCB8fCBuZXcgRE9NUmVjdCgtOTk5OSwgLTk5OTksIDAsIDApO1xuICB9XG5cbiAgb25Nb3VzZUVudGVyKCkge1xuICAgIHRoaXMuaXNJbnRlcmFjdGluZy5zZXQodHJ1ZSk7XG4gIH1cblxuICBvbk1vdXNlTGVhdmUoKSB7XG4gICAgdGhpcy5pc0ludGVyYWN0aW5nLnNldChmYWxzZSk7XG4gIH1cblxuICBvbkNvbnRhaW5lck1vdXNlRG93bihldmVudDogTW91c2VFdmVudCkge1xuICAgIGlmIChldmVudC50YXJnZXQgPT09IGV2ZW50LmN1cnJlbnRUYXJnZXQpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuICB9XG5cbiAgb25CdXR0b25Nb3VzZURvd24oZXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlbGVjdGlvbiBzdHJhdGVneSB0byBhdm9pZCBwYXJ0aWFsIG5vZGUgZHJhZ2dpbmcgKGdob3N0IHRhYmxlIGlzc3VlKS5cbiAgICovXG4gIG9uRHJhZ0hhbmRsZU1vdXNlRG93bihldmVudDogTW91c2VFdmVudCkge1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIGNvbnN0IGVkID0gdGhpcy5lZGl0b3IoKTtcbiAgICBjb25zdCBkYXRhID0gdGhpcy5ob3ZlcmVkRGF0YSgpIHx8IHRoaXMubGFzdFZhbGlkRGF0YTtcbiAgICBpZiAoZWQgJiYgZGF0YSkge1xuICAgICAgLy8gRm9yY2Ugd2hvbGUtbm9kZSBzZWxlY3Rpb24uIFRoaXMgaXMgY3J1Y2lhbCBmb3IgYXRvbWljIG5vZGVzIGxpa2UgdGFibGVzIGFuZCBpbWFnZXMuXG4gICAgICBlZC5jb21tYW5kcy5zZXROb2RlU2VsZWN0aW9uKGRhdGEucG9zKTtcbiAgICB9XG4gIH1cblxuICBhZGRCbG9jayhldmVudDogTW91c2VFdmVudCkge1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIGNvbnN0IGVkID0gdGhpcy5lZGl0b3IoKTtcbiAgICBjb25zdCBkYXRhID0gdGhpcy5ob3ZlcmVkRGF0YSgpIHx8IHRoaXMubGFzdFZhbGlkRGF0YTtcbiAgICBpZiAoIWVkIHx8ICFkYXRhKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgeyBwb3MsIG5vZGUgfSA9IGRhdGE7XG4gICAgaWYgKG5vZGUuY29udGVudC5zaXplID09PSAwKSB7XG4gICAgICBlZC5jaGFpbigpXG4gICAgICAgIC5mb2N1cygpXG4gICAgICAgIC5zZXRUZXh0U2VsZWN0aW9uKHBvcyArIDEpXG4gICAgICAgIC5pbnNlcnRDb250ZW50KFwiL1wiKVxuICAgICAgICAucnVuKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG5leHRQb3MgPSBwb3MgKyBub2RlLm5vZGVTaXplO1xuICAgICAgZWQuY2hhaW4oKVxuICAgICAgICAuZm9jdXMoKVxuICAgICAgICAuaW5zZXJ0Q29udGVudEF0KG5leHRQb3MsIHsgdHlwZTogXCJwYXJhZ3JhcGhcIiwgY29udGVudDogW3sgdHlwZTogXCJ0ZXh0XCIsIHRleHQ6IFwiL1wiIH1dIH0pXG4gICAgICAgIC5zZXRUZXh0U2VsZWN0aW9uKG5leHRQb3MgKyAyKVxuICAgICAgICAucnVuKCk7XG4gICAgfVxuXG4gICAgdGhpcy5pc0ludGVyYWN0aW5nLnNldChmYWxzZSk7XG4gICAgdGhpcy5oaWRlVGlwcHkoKTtcbiAgfVxuXG4gIG9uRHJhZ1N0YXJ0KGV2ZW50OiBEcmFnRXZlbnQpIHtcbiAgICBjb25zdCBlZCA9IHRoaXMuZWRpdG9yKCk7XG4gICAgY29uc3QgZGF0YSA9IHRoaXMuaG92ZXJlZERhdGEoKSB8fCB0aGlzLmxhc3RWYWxpZERhdGE7XG4gICAgaWYgKCFlZCB8fCAhZGF0YSB8fCAhZXZlbnQuZGF0YVRyYW5zZmVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgeyBlbGVtZW50LCBwb3MgfSA9IGRhdGE7XG4gICAgY29uc3QgdmlldyA9IGVkLnZpZXc7XG5cbiAgICAvLyAxLiBGb3JjZSB0aGUgZWRpdG9yIHRvIGZvY3VzIGFuZCBzZWxlY3QgdGhlIEVOVElSRSBub2RlXG4gICAgdmlldy5mb2N1cygpO1xuICAgIGVkLmNvbW1hbmRzLnNldE5vZGVTZWxlY3Rpb24ocG9zKTtcblxuICAgIC8vIDIuIEJyb3dzZXIgRHJhZyBJbWFnZSAmIG1ldGFkYXRhXG4gICAgZXZlbnQuZGF0YVRyYW5zZmVyLnNldERyYWdJbWFnZShlbGVtZW50LCAwLCAxMCk7XG4gICAgZXZlbnQuZGF0YVRyYW5zZmVyLmVmZmVjdEFsbG93ZWQgPSBcIm1vdmVcIjtcbiAgICBldmVudC5kYXRhVHJhbnNmZXIuc2V0RGF0YShcInRleHQvcGxhaW5cIiwgXCJcIik7XG5cbiAgICAvLyAzLiBQUk8tSEFDSzogSW5kaWNhdGUgdGhpcyBpcyBhIG1vdmUgb2YgdGhlIGN1cnJlbnQgc2VsZWN0aW9uICh0aGUgd2hvbGUgbm9kZSlcbiAgICAodmlldyBhcyB1bmtub3duIGFzIHsgZHJhZ2dpbmc6IHVua25vd24gfSkuZHJhZ2dpbmcgPSB7XG4gICAgICBzbGljZTogZWQuc3RhdGUuc2VsZWN0aW9uLmNvbnRlbnQoKSxcbiAgICAgIG1vdmU6IHRydWUsXG4gICAgfTtcblxuICAgIC8vIDQuIERpc3BhdGNoIHZpcnR1YWwgZHJhZ3N0YXJ0XG4gICAgY29uc3QgcG1FdmVudCA9IG5ldyBEcmFnRXZlbnQoXCJkcmFnc3RhcnRcIiwge1xuICAgICAgZGF0YVRyYW5zZmVyOiBldmVudC5kYXRhVHJhbnNmZXIsXG4gICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgY2FuY2VsYWJsZTogdHJ1ZSxcbiAgICB9KTtcbiAgICBlbGVtZW50LmRpc3BhdGNoRXZlbnQocG1FdmVudCk7XG5cbiAgICAvLyA1LiBDbGVhbnVwIFVJXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLmhpZGVUaXBweSgpO1xuICAgICAgdGhpcy5pc0ludGVyYWN0aW5nLnNldChmYWxzZSk7XG4gICAgfSwgMCk7XG4gIH1cblxuICBvbkRyYWdFbmQoKSB7XG4gICAgdGhpcy5pc0ludGVyYWN0aW5nLnNldChmYWxzZSk7XG4gIH1cbn1cbiJdfQ==