@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,309 @@
1
+ import { Component, input, ChangeDetectionStrategy, computed, inject } from "@angular/core";
2
+ import { AteButtonComponent } from "../../ui/ate-button.component";
3
+ import { AteSeparatorComponent } from "../../ui/ate-separator.component";
4
+ import { AteImageService } from "../../../services/ate-image.service";
5
+ import { ATE_IMAGE_BUBBLE_MENU_KEYS, } from "../../../models/ate-bubble-menu.model";
6
+ import { ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG } from "../../../config/ate-editor.config";
7
+ import { AteBaseBubbleMenu } from "../base/ate-base-bubble-menu";
8
+ import * as i0 from "@angular/core";
9
+ export class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.t = this.i18nService.imageUpload;
13
+ this.imageService = inject(AteImageService);
14
+ this.config = input(ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG);
15
+ this.imageUpload = input({});
16
+ this.imageBubbleMenuConfig = computed(() => {
17
+ const c = this.config();
18
+ const result = {};
19
+ ATE_IMAGE_BUBBLE_MENU_KEYS.forEach(key => {
20
+ result[key] = c[key] ?? true;
21
+ });
22
+ return result;
23
+ });
24
+ this.hasAlignmentButtons = computed(() => this.imageBubbleMenuConfig().alignLeft ||
25
+ this.imageBubbleMenuConfig().alignCenter ||
26
+ this.imageBubbleMenuConfig().alignRight);
27
+ this.hasResizeButtons = computed(() => {
28
+ const c = this.imageBubbleMenuConfig();
29
+ return c.resizeSmall || c.resizeMedium || c.resizeLarge || c.resizeOriginal;
30
+ });
31
+ }
32
+ shouldShow() {
33
+ const { nodes, isEditable, isFocused, selection } = this.state();
34
+ if (this.editorCommands.linkEditMode() || this.editorCommands.colorEditMode()) {
35
+ return false;
36
+ }
37
+ // In read-only mode, focus reporting can be unreliable,
38
+ // so we show the menu as long as an image is selected.
39
+ if (!isEditable) {
40
+ return nodes.isImage && selection.type === "node";
41
+ }
42
+ return nodes.isImage && isFocused;
43
+ }
44
+ getSelectionRect() {
45
+ const ed = this.editor();
46
+ if (!ed) {
47
+ return new DOMRect(0, 0, 0, 0);
48
+ }
49
+ const { from } = ed.state.selection;
50
+ try {
51
+ // 1. Direct ProseMirror approach: get DOM node at position
52
+ const dom = ed.view.nodeDOM(from);
53
+ if (dom instanceof HTMLElement) {
54
+ // If it's a resizable container, look for the image inside
55
+ if (dom.classList.contains("resizable-image-container")) {
56
+ const img = dom.querySelector("img");
57
+ if (img) {
58
+ return img.getBoundingClientRect();
59
+ }
60
+ }
61
+ return dom.getBoundingClientRect();
62
+ }
63
+ }
64
+ catch (_e) {
65
+ // Fallback if nodeDOM fails
66
+ }
67
+ // 2. Ultimate fallback: find selected image in DOM
68
+ const selectedImg = ed.view.dom.querySelector("img.selected, .resizable-image-container.selected img");
69
+ if (selectedImg) {
70
+ return selectedImg.getBoundingClientRect();
71
+ }
72
+ // If nothing found at all
73
+ return new DOMRect(-9999, -9999, 0, 0);
74
+ }
75
+ executeCommand(editor, command, ..._args) {
76
+ switch (command) {
77
+ case "changeImage":
78
+ this.changeImage();
79
+ break;
80
+ case "downloadImage":
81
+ this.editorCommands.downloadImage(editor);
82
+ break;
83
+ case "resizeSmall":
84
+ this.imageService.resizeImageToSmall(editor);
85
+ break;
86
+ case "resizeMedium":
87
+ this.imageService.resizeImageToMedium(editor);
88
+ break;
89
+ case "resizeLarge":
90
+ this.imageService.resizeImageToLarge(editor);
91
+ break;
92
+ case "resizeOriginal":
93
+ this.imageService.resizeImageToOriginal(editor);
94
+ break;
95
+ case "deleteImage":
96
+ this.deleteImage();
97
+ break;
98
+ case "alignLeft":
99
+ editor.chain().focus().setTextAlign("left").run();
100
+ break;
101
+ case "alignCenter":
102
+ editor.chain().focus().setTextAlign("center").run();
103
+ break;
104
+ case "alignRight":
105
+ editor.chain().focus().setTextAlign("right").run();
106
+ break;
107
+ }
108
+ }
109
+ async changeImage() {
110
+ const ed = this.editor();
111
+ if (!ed) {
112
+ return;
113
+ }
114
+ try {
115
+ // Use dedicated method to replace an existing image
116
+ await this.imageService.selectAndReplaceImage(ed, this.imageUpload());
117
+ }
118
+ catch (error) {
119
+ console.error(this.i18nService.imageUpload().uploadError, error);
120
+ }
121
+ }
122
+ deleteImage() {
123
+ const ed = this.editor();
124
+ if (ed) {
125
+ ed.chain().focus().deleteSelection().run();
126
+ }
127
+ }
128
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageBubbleMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
129
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AteImageBubbleMenuComponent, isStandalone: true, selector: "ate-image-bubble-menu", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
130
+ <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
131
+ @if (imageBubbleMenuConfig().changeImage && editor().isEditable) {
132
+ <ate-button
133
+ icon="drive_file_rename_outline"
134
+ [title]="t().changeImage"
135
+ (buttonClick)="onCommand('changeImage', $event)"></ate-button>
136
+ }
137
+ @if (imageBubbleMenuConfig().downloadImage) {
138
+ <ate-button
139
+ icon="download"
140
+ [title]="t().downloadImage"
141
+ (buttonClick)="onCommand('downloadImage', $event)"></ate-button>
142
+ }
143
+ @if (imageBubbleMenuConfig().separator && hasResizeButtons() && editor().isEditable) {
144
+ <ate-separator />
145
+ }
146
+ @if (imageBubbleMenuConfig().resizeSmall && editor().isEditable) {
147
+ <ate-button
148
+ icon="crop_square"
149
+ iconSize="small"
150
+ [title]="t().resizeSmall"
151
+ (buttonClick)="onCommand('resizeSmall', $event)"></ate-button>
152
+ }
153
+ @if (imageBubbleMenuConfig().resizeMedium && editor().isEditable) {
154
+ <ate-button
155
+ icon="crop_square"
156
+ iconSize="medium"
157
+ [title]="t().resizeMedium"
158
+ (buttonClick)="onCommand('resizeMedium', $event)"></ate-button>
159
+ }
160
+ @if (imageBubbleMenuConfig().resizeLarge && editor().isEditable) {
161
+ <ate-button
162
+ icon="crop_square"
163
+ iconSize="large"
164
+ [title]="t().resizeLarge"
165
+ (buttonClick)="onCommand('resizeLarge', $event)"></ate-button>
166
+ }
167
+ @if (imageBubbleMenuConfig().resizeOriginal && editor().isEditable) {
168
+ <ate-button
169
+ icon="photo_size_select_actual"
170
+ [title]="t().resizeOriginal"
171
+ (buttonClick)="onCommand('resizeOriginal', $event)"></ate-button>
172
+ }
173
+ @if (imageBubbleMenuConfig().separator && hasAlignmentButtons() && editor().isEditable) {
174
+ <ate-separator />
175
+ }
176
+ @if (imageBubbleMenuConfig().alignLeft && editor().isEditable) {
177
+ <ate-button
178
+ icon="format_align_left"
179
+ [title]="t().alignLeft"
180
+ [active]="editor().isActive({ textAlign: 'left' })"
181
+ (buttonClick)="onCommand('alignLeft', $event)"></ate-button>
182
+ }
183
+ @if (imageBubbleMenuConfig().alignCenter && editor().isEditable) {
184
+ <ate-button
185
+ icon="format_align_center"
186
+ [title]="t().alignCenter"
187
+ [active]="editor().isActive({ textAlign: 'center' })"
188
+ (buttonClick)="onCommand('alignCenter', $event)"></ate-button>
189
+ }
190
+ @if (imageBubbleMenuConfig().alignRight && editor().isEditable) {
191
+ <ate-button
192
+ icon="format_align_right"
193
+ [title]="t().alignRight"
194
+ [active]="editor().isActive({ textAlign: 'right' })"
195
+ (buttonClick)="onCommand('alignRight', $event)"></ate-button>
196
+ }
197
+
198
+ @if (
199
+ imageBubbleMenuConfig().separator &&
200
+ imageBubbleMenuConfig().deleteImage &&
201
+ editor().isEditable
202
+ ) {
203
+ <ate-separator />
204
+ }
205
+ @if (imageBubbleMenuConfig().deleteImage && editor().isEditable) {
206
+ <ate-button
207
+ icon="delete"
208
+ [title]="t().deleteImage"
209
+ variant="danger"
210
+ (buttonClick)="onCommand('deleteImage', $event)"></ate-button>
211
+ }
212
+ </div>
213
+ `, isInline: true, dependencies: [{ kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }, { kind: "component", type: AteSeparatorComponent, selector: "ate-separator" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
214
+ }
215
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageBubbleMenuComponent, decorators: [{
216
+ type: Component,
217
+ args: [{
218
+ selector: "ate-image-bubble-menu",
219
+ standalone: true,
220
+ changeDetection: ChangeDetectionStrategy.OnPush,
221
+ imports: [AteButtonComponent, AteSeparatorComponent],
222
+ template: `
223
+ <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
224
+ @if (imageBubbleMenuConfig().changeImage && editor().isEditable) {
225
+ <ate-button
226
+ icon="drive_file_rename_outline"
227
+ [title]="t().changeImage"
228
+ (buttonClick)="onCommand('changeImage', $event)"></ate-button>
229
+ }
230
+ @if (imageBubbleMenuConfig().downloadImage) {
231
+ <ate-button
232
+ icon="download"
233
+ [title]="t().downloadImage"
234
+ (buttonClick)="onCommand('downloadImage', $event)"></ate-button>
235
+ }
236
+ @if (imageBubbleMenuConfig().separator && hasResizeButtons() && editor().isEditable) {
237
+ <ate-separator />
238
+ }
239
+ @if (imageBubbleMenuConfig().resizeSmall && editor().isEditable) {
240
+ <ate-button
241
+ icon="crop_square"
242
+ iconSize="small"
243
+ [title]="t().resizeSmall"
244
+ (buttonClick)="onCommand('resizeSmall', $event)"></ate-button>
245
+ }
246
+ @if (imageBubbleMenuConfig().resizeMedium && editor().isEditable) {
247
+ <ate-button
248
+ icon="crop_square"
249
+ iconSize="medium"
250
+ [title]="t().resizeMedium"
251
+ (buttonClick)="onCommand('resizeMedium', $event)"></ate-button>
252
+ }
253
+ @if (imageBubbleMenuConfig().resizeLarge && editor().isEditable) {
254
+ <ate-button
255
+ icon="crop_square"
256
+ iconSize="large"
257
+ [title]="t().resizeLarge"
258
+ (buttonClick)="onCommand('resizeLarge', $event)"></ate-button>
259
+ }
260
+ @if (imageBubbleMenuConfig().resizeOriginal && editor().isEditable) {
261
+ <ate-button
262
+ icon="photo_size_select_actual"
263
+ [title]="t().resizeOriginal"
264
+ (buttonClick)="onCommand('resizeOriginal', $event)"></ate-button>
265
+ }
266
+ @if (imageBubbleMenuConfig().separator && hasAlignmentButtons() && editor().isEditable) {
267
+ <ate-separator />
268
+ }
269
+ @if (imageBubbleMenuConfig().alignLeft && editor().isEditable) {
270
+ <ate-button
271
+ icon="format_align_left"
272
+ [title]="t().alignLeft"
273
+ [active]="editor().isActive({ textAlign: 'left' })"
274
+ (buttonClick)="onCommand('alignLeft', $event)"></ate-button>
275
+ }
276
+ @if (imageBubbleMenuConfig().alignCenter && editor().isEditable) {
277
+ <ate-button
278
+ icon="format_align_center"
279
+ [title]="t().alignCenter"
280
+ [active]="editor().isActive({ textAlign: 'center' })"
281
+ (buttonClick)="onCommand('alignCenter', $event)"></ate-button>
282
+ }
283
+ @if (imageBubbleMenuConfig().alignRight && editor().isEditable) {
284
+ <ate-button
285
+ icon="format_align_right"
286
+ [title]="t().alignRight"
287
+ [active]="editor().isActive({ textAlign: 'right' })"
288
+ (buttonClick)="onCommand('alignRight', $event)"></ate-button>
289
+ }
290
+
291
+ @if (
292
+ imageBubbleMenuConfig().separator &&
293
+ imageBubbleMenuConfig().deleteImage &&
294
+ editor().isEditable
295
+ ) {
296
+ <ate-separator />
297
+ }
298
+ @if (imageBubbleMenuConfig().deleteImage && editor().isEditable) {
299
+ <ate-button
300
+ icon="delete"
301
+ [title]="t().deleteImage"
302
+ variant="danger"
303
+ (buttonClick)="onCommand('deleteImage', $event)"></ate-button>
304
+ }
305
+ </div>
306
+ `,
307
+ }]
308
+ }] });
309
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRlLWltYWdlLWJ1YmJsZS1tZW51LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItdGlwdGFwLWVkaXRvci9zcmMvbGliL2NvbXBvbmVudHMvYnViYmxlLW1lbnVzL2ltYWdlL2F0ZS1pbWFnZS1idWJibGUtbWVudS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsdUJBQXVCLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUU1RixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNuRSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUN6RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDdEUsT0FBTyxFQUVMLDBCQUEwQixHQUMzQixNQUFNLHVDQUF1QyxDQUFDO0FBQy9DLE9BQU8sRUFBRSxvQ0FBb0MsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3pGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDhCQUE4QixDQUFDOztBQThGakUsTUFBTSxPQUFPLDJCQUE0QixTQUFRLGlCQUFpQjtJQTNGbEU7O1FBNEZXLE1BQUMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQztRQUN6QixpQkFBWSxHQUFHLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUV4RCxXQUFNLEdBQUcsS0FBSyxDQUEyQixvQ0FBb0MsQ0FBQyxDQUFDO1FBRS9FLGdCQUFXLEdBQUcsS0FBSyxDQUF3QixFQUFFLENBQUMsQ0FBQztRQUUvQywwQkFBcUIsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFO1lBQ3BDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN4QixNQUFN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QUFDO29CQUNULFFBQVEsRUFBRSx1QkFBdUI7b0JBQ2pDLFVBQVUsRUFBRSxJQUFJO29CQUNoQixlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTtvQkFDL0MsT0FBTyxFQUFFLENBQUMsa0JBQWtCLEVBQUUscUJBQXFCLENBQUM7b0JBQ3BELFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0ZUO2lCQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBpbnB1dCwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIGNvbXB1dGVkLCBpbmplY3QgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgdHlwZSBFZGl0b3IgfSBmcm9tIFwiQHRpcHRhcC9jb3JlXCI7XG5pbXBvcnQgeyBBdGVCdXR0b25Db21wb25lbnQgfSBmcm9tIFwiLi4vLi4vdWkvYXRlLWJ1dHRvbi5jb21wb25lbnRcIjtcbmltcG9ydCB7IEF0ZVNlcGFyYXRvckNvbXBvbmVudCB9IGZyb20gXCIuLi8uLi91aS9hdGUtc2VwYXJhdG9yLmNvbXBvbmVudFwiO1xuaW1wb3J0IHsgQXRlSW1hZ2VTZXJ2aWNlIH0gZnJvbSBcIi4uLy4uLy4uL3NlcnZpY2VzL2F0ZS1pbWFnZS5zZXJ2aWNlXCI7XG5pbXBvcnQge1xuICBBdGVJbWFnZUJ1YmJsZU1lbnVDb25maWcsXG4gIEFURV9JTUFHRV9CVUJCTEVfTUVOVV9LRVlTLFxufSBmcm9tIFwiLi4vLi4vLi4vbW9kZWxzL2F0ZS1idWJibGUtbWVudS5tb2RlbFwiO1xuaW1wb3J0IHsgQVRFX0RFRkFVTFRfSU1BR0VfQlVCQkxFX01FTlVfQ09ORklHIH0gZnJvbSBcIi4uLy4uLy4uL2NvbmZpZy9hdGUtZWRpdG9yLmNvbmZpZ1wiO1xuaW1wb3J0IHsgQXRlQmFzZUJ1YmJsZU1lbnUgfSBmcm9tIFwiLi4vYmFzZS9hdGUtYmFzZS1idWJibGUtbWVudVwiO1xuaW1wb3J0IHsgQXRlSW1hZ2VVcGxvYWRPcHRpb25zIH0gZnJvbSBcIi4uLy4uLy4uL21vZGVscy9hdGUtaW1hZ2UubW9kZWxcIjtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcImF0ZS1pbWFnZS1idWJibGUtbWVudVwiLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgaW1wb3J0czogW0F0ZUJ1dHRvbkNvbXBvbmVudCwgQXRlU2VwYXJhdG9yQ29tcG9uZW50XSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2ICNtZW51UmVmIGNsYXNzPVwiYnViYmxlLW1lbnVcIiAobW91c2Vkb3duKT1cIiRldmVudC5wcmV2ZW50RGVmYXVsdCgpXCI+XG4gICAgICBAaWYgKGltYWdlQnViYmxlTWVudUNvbmZpZygpLmNoYW5nZUltYWdlICYmIGVkaXRvcigpLmlzRWRpdGFibGUpIHtcbiAgICAgICAgPGF0ZS1idXR0b25cbiAgICAgICAgICBpY29uPVwiZHJpdmVfZmlsZV9yZW5hbWVfb3V0bGluZVwiXG4gICAgICAgICAgW3RpdGxlXT1cInQoKS5jaGFuZ2VJbWFnZVwiXG4gICAgICAgICAgKGJ1dHRvbkNsaWNrKT1cIm9uQ29tbWFuZCgnY2hhbmdlSW1hZ2UnLCAkZXZlbnQpXCI+PC9hdGUtYnV0dG9uPlxuICAgICAgfVxuICAgICAgQGlmIChpbWFnZUJ1YmJsZU1lbnVDb25maWcoKS5kb3dubG9hZEltYWdlKSB7XG4gICAgICAgIDxhdGUtYnV0dG9uXG4gICAgICAgICAgaWNvbj1cImRvd25sb2FkXCJcbiAgICAgICAgICBbdGl0bGVdPVwidCgpLmRvd25sb2FkSW1hZ2VcIlxuICAgICAgICAgIChidXR0b25DbGljayk9XCJvbkNvbW1hbmQoJ2Rvd25sb2FkSW1hZ2UnLCAkZXZlbnQpXCI+PC9hdGUtYnV0dG9uPlxuICAgICAgfVxuICAgICAgQGlmIChpbWFnZUJ1YmJsZU1lbnVDb25maWcoKS5zZXBhcmF0b3IgJiYgaGFzUmVzaXplQnV0dG9ucygpICYmIGVkaXRvcigpLmlzRWRpdGFibGUpIHtcbiAgICAgICAgPGF0ZS1zZXBhcmF0b3IgLz5cbiAgICAgIH1cbiAgICAgIEBpZiAoaW1hZ2VCdWJibGVNZW51Q29uZmlnKCkucmVzaXplU21hbGwgJiYgZWRpdG9yKCkuaXNFZGl0YWJsZSkge1xuICAgICAgICA8YXRlLWJ1dHRvblxuICAgICAgICAgIGljb249XCJjcm9wX3NxdWFyZVwiXG4gICAgICAgICAgaWNvblNpemU9XCJzbWFsbFwiXG4gICAgICAgICAgW3RpdGxlXT1cInQoKS5yZXNpemVTbWFsbFwiXG4gICAgICAgICAgKGJ1dHRvbkNsaWNrKT1cIm9uQ29tbWFuZCgncmVzaXplU21hbGwnLCAkZXZlbnQpXCI+PC9hdGUtYnV0dG9uPlxuICAgICAgfVxuICAgICAgQGlmIChpbWFnZUJ1YmJsZU1lbnVDb25maWcoKS5yZXNpemVNZWRpdW0gJiYgZWRpdG9yKCkuaXNFZGl0YWJsZSkge1xuICAgICAgICA8YXRlLWJ1dHRvblxuICAgICAgICAgIGljb249XCJjcm9wX3NxdWFyZVwiXG4gICAgICAgICAgaWNvblNpemU9XCJtZWRpdW1cIlxuICAgICAgICAgIFt0aXRsZV09XCJ0KCkucmVzaXplTWVkaXVtXCJcbiAgICAgICAgICAoYnV0dG9uQ2xpY2spPVwib25Db21tYW5kKCdyZXNpemVNZWRpdW0nLCAkZXZlbnQpXCI+PC9hdGUtYnV0dG9uPlxuICAgICAgfVxuICAgICAgQGlmIChpbWFnZUJ1YmJsZU1lbnVDb25maWcoKS5yZXNpemVMYXJnZSAmJiBlZGl0b3IoKS5pc0VkaXRhYmxlKSB7XG4gICAgICAgIDxhdGUtYnV0dG9uXG4gICAgICAgICAgaWNvbj1cImNyb3Bfc3F1YXJlXCJcbiAgICAgICAgICBpY29uU2l6ZT1cImxhcmdlXCJcbiAgICAgICAgICBbdGl0bGVdPVwidCgpLnJlc2l6ZUxhcmdlXCJcbiAgICAgICAgICAoYnV0dG9uQ2xpY2spPVwib25Db21tYW5kKCdyZXNpemVMYXJnZScsICRldmVudClcIj48L2F0ZS1idXR0b24+XG4gICAgICB9XG4gICAgICBAaWYgKGltYWdlQnViYmxlTWVudUNvbmZpZygpLnJlc2l6ZU9yaWdpbmFsICYmIGVkaXRvcigpLmlzRWRpdGFibGUpIHtcbiAgICAgICAgPGF0ZS1idXR0b25cbiAgICAgICAgICBpY29uPVwicGhvdG9fc2l6ZV9zZWxlY3RfYWN0dWFsXCJcbiAgICAgICAgICBbdGl0bGVdPVwidCgpLnJlc2l6ZU9yaWdpbmFsXCJcbiAgICAgICAgICAoYnV0dG9uQ2xpY2spPVwib25Db21tYW5kKCdyZXNpemVPcmlnaW5hbCcsICRldmVudClcIj48L2F0ZS1idXR0b24+XG4gICAgICB9XG4gICAgICBAaWYgKGltYWdlQnViYmxlTWVudUNvbmZpZygpLnNlcGFyYXRvciAmJiBoYXNBbGlnbm1lbnRCdXR0b25zKCkgJiYgZWRpdG9yKCkuaXNFZGl0YWJsZSkge1xuICAgICAgICA8YXRlLXNlcGFyYXRvciAvPlxuICAgICAgfVxuICAgICAgQGlmIChpbWFnZUJ1YmJsZU1lbnVDb25maWcoKS5hbGlnbkxlZnQgJiYgZWRpdG9yKCkuaXNFZGl0YWJsZSkge1xuICAgICAgICA8YXRlLWJ1dHRvblxuICAgICAgICAgIGljb249XCJmb3JtYXRfYWxpZ25fbGVmdFwiXG4gICAgICAgICAgW3RpdGxlXT1cInQoKS5hbGlnbkxlZnRcIlxuICAgICAgICAgIFthY3RpdmVdPVwiZWRpdG9yKCkuaXNBY3RpdmUoeyB0ZXh0QWxpZ246ICdsZWZ0JyB9KVwiXG4gICAgICAgICAgKGJ1dHRvbkNsaWNrKT1cIm9uQ29tbWFuZCgnYWxpZ25MZWZ0JywgJGV2ZW50KVwiPjwvYXRlLWJ1dHRvbj5cbiAgICAgIH1cbiAgICAgIEBpZiAoaW1hZ2VCdWJibGVNZW51Q29uZmlnKCkuYWxpZ25DZW50ZXIgJiYgZWRpdG9yKCkuaXNFZGl0YWJsZSkge1xuICAgICAgICA8YXRlLWJ1dHRvblxuICAgICAgICAgIGljb249XCJmb3JtYXRfYWxpZ25fY2VudGVyXCJcbiAgICAgICAgICBbdGl0bGVdPVwidCgpLmFsaWduQ2VudGVyXCJcbiAgICAgICAgICBbYWN0aXZlXT1cImVkaXRvcigpLmlzQWN0aXZlKHsgdGV4dEFsaWduOiAnY2VudGVyJyB9KVwiXG4gICAgICAgICAgKGJ1dHRvbkNsaWNrKT1cIm9uQ29tbWFuZCgnYWxpZ25DZW50ZXInLCAkZXZlbnQpXCI+PC9hdGUtYnV0dG9uPlxuICAgICAgfVxuICAgICAgQGlmIChpbWFnZUJ1YmJsZU1lbnVDb25maWcoKS5hbGlnblJpZ2h0ICYmIGVkaXRvcigpLmlzRWRpdGFibGUpIHtcbiAgICAgICAgPGF0ZS1idXR0b25cbiAgICAgICAgICBpY29uPVwiZm9ybWF0X2FsaWduX3JpZ2h0XCJcbiAgICAgICAgICBbdGl0bGVdPVwidCgpLmFsaWduUmlnaHRcIlxuICAgICAgICAgIFthY3RpdmVdPVwiZWRpdG9yKCkuaXNBY3RpdmUoeyB0ZXh0QWxpZ246ICdyaWdodCcgfSlcIlxuICAgICAgICAgIChidXR0b25DbGljayk9XCJvbkNvbW1hbmQoJ2FsaWduUmlnaHQnLCAkZXZlbnQpXCI+PC9hdGUtYnV0dG9uPlxuICAgICAgfVxuXG4gICAgICBAaWYgKFxuICAgICAgICBpbWFnZUJ1YmJsZU1lbnVDb25maWcoKS5zZXBhcmF0b3IgJiZcbiAgICAgICAgaW1hZ2VCdWJibGVNZW51Q29uZmlnKCkuZGVsZXRlSW1hZ2UgJiZcbiAgICAgICAgZWRpdG9yKCkuaXNFZGl0YWJsZVxuICAgICAgKSB7XG4gICAgICAgIDxhdGUtc2VwYXJhdG9yIC8+XG4gICAgICB9XG4gICAgICBAaWYgKGltYWdlQnViYmxlTWVudUNvbmZpZygpLmRlbGV0ZUltYWdlICYmIGVkaXRvcigpLmlzRWRpdGFibGUpIHtcbiAgICAgICAgPGF0ZS1idXR0b25cbiAgICAgICAgICBpY29uPVwiZGVsZXRlXCJcbiAgICAgICAgICBbdGl0bGVdPVwidCgpLmRlbGV0ZUltYWdlXCJcbiAgICAgICAgICB2YXJpYW50PVwiZGFuZ2VyXCJcbiAgICAgICAgICAoYnV0dG9uQ2xpY2spPVwib25Db21tYW5kKCdkZWxldGVJbWFnZScsICRldmVudClcIj48L2F0ZS1idXR0b24+XG4gICAgICB9XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIEF0ZUltYWdlQnViYmxlTWVudUNvbXBvbmVudCBleHRlbmRzIEF0ZUJhc2VCdWJibGVNZW51IHtcbiAgcmVhZG9ubHkgdCA9IHRoaXMuaTE4blNlcnZpY2UuaW1hZ2VVcGxvYWQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgaW1hZ2VTZXJ2aWNlID0gaW5qZWN0KEF0ZUltYWdlU2VydmljZSk7XG5cbiAgY29uZmlnID0gaW5wdXQ8QXRlSW1hZ2VCdWJibGVNZW51Q29uZmlnPihBVEVfREVGQVVMVF9JTUFHRV9CVUJCTEVfTUVOVV9DT05GSUcpO1xuXG4gIGltYWdlVXBsb2FkID0gaW5wdXQ8QXRlSW1hZ2VVcGxvYWRPcHRpb25zPih7fSk7XG5cbiAgaW1hZ2VCdWJibGVNZW51Q29uZmlnID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IGMgPSB0aGlzLmNvbmZpZygpO1xuICAgIGNvbnN0IHJlc3VsdDogUmVjb3JkPHN0cmluZywgYm9vbGVhbj4gPSB7fTtcbiAgICBBVEVfSU1BR0VfQlVCQkxFX01FTlVfS0VZUy5mb3JFYWNoKGtleSA9PiB7XG4gICAgICByZXN1bHRba2V5XSA9IGNba2V5XSA/PyB0cnVlO1xuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQgYXMgUmVxdWlyZWQ8QXRlSW1hZ2VCdWJibGVNZW51Q29uZmlnPjtcbiAgfSk7XG5cbiAgaGFzQWxpZ25tZW50QnV0dG9ucyA9IGNvbXB1dGVkKFxuICAgICgpID0+XG4gICAgICB0aGlzLmltYWdlQnViYmxlTWVudUNvbmZpZygpLmFsaWduTGVmdCB8fFxuICAgICAgdGhpcy5pbWFnZUJ1YmJsZU1lbnVDb25maWcoKS5hbGlnbkNlbnRlciB8fFxuICAgICAgdGhpcy5pbWFnZUJ1YmJsZU1lbnVDb25maWcoKS5hbGlnblJpZ2h0XG4gICk7XG5cbiAgaGFzUmVzaXplQnV0dG9ucyA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBjID0gdGhpcy5pbWFnZUJ1YmJsZU1lbnVDb25maWcoKTtcbiAgICByZXR1cm4gYy5yZXNpemVTbWFsbCB8fCBjLnJlc2l6ZU1lZGl1bSB8fCBjLnJlc2l6ZUxhcmdlIHx8IGMucmVzaXplT3JpZ2luYWw7XG4gIH0pO1xuXG4gIG92ZXJyaWRlIHNob3VsZFNob3coKTogYm9vbGVhbiB7XG4gICAgY29uc3QgeyBub2RlcywgaXNFZGl0YWJsZSwgaXNGb2N1c2VkLCBzZWxlY3Rpb24gfSA9IHRoaXMuc3RhdGUoKTtcblxuICAgIGlmICh0aGlzLmVkaXRvckNvbW1hbmRzLmxpbmtFZGl0TW9kZSgpIHx8IHRoaXMuZWRpdG9yQ29tbWFuZHMuY29sb3JFZGl0TW9kZSgpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gSW4gcmVhZC1vbmx5IG1vZGUsIGZvY3VzIHJlcG9ydGluZyBjYW4gYmUgdW5yZWxpYWJsZSxcbiAgICAvLyBzbyB3ZSBzaG93IHRoZSBtZW51IGFzIGxvbmcgYXMgYW4gaW1hZ2UgaXMgc2VsZWN0ZWQuXG4gICAgaWYgKCFpc0VkaXRhYmxlKSB7XG4gICAgICByZXR1cm4gbm9kZXMuaXNJbWFnZSAmJiBzZWxlY3Rpb24udHlwZSA9PT0gXCJub2RlXCI7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5vZGVzLmlzSW1hZ2UgJiYgaXNGb2N1c2VkO1xuICB9XG5cbiAgb3ZlcnJpZGUgZ2V0U2VsZWN0aW9uUmVjdCgpOiBET01SZWN0IHtcbiAgICBjb25zdCBlZCA9IHRoaXMuZWRpdG9yKCk7XG4gICAgaWYgKCFlZCkge1xuICAgICAgcmV0dXJuIG5ldyBET01SZWN0KDAsIDAsIDAsIDApO1xuICAgIH1cblxuICAgIGNvbnN0IHsgZnJvbSB9ID0gZWQuc3RhdGUuc2VsZWN0aW9uO1xuXG4gICAgdHJ5IHtcbiAgICAgIC8vIDEuIERpcmVjdCBQcm9zZU1pcnJvciBhcHByb2FjaDogZ2V0IERPTSBub2RlIGF0IHBvc2l0aW9uXG4gICAgICBjb25zdCBkb20gPSBlZC52aWV3Lm5vZGVET00oZnJvbSk7XG4gICAgICBpZiAoZG9tIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgLy8gSWYgaXQncyBhIHJlc2l6YWJsZSBjb250YWluZXIsIGxvb2sgZm9yIHRoZSBpbWFnZSBpbnNpZGVcbiAgICAgICAgaWYgKGRvbS5jbGFzc0xpc3QuY29udGFpbnMoXCJyZXNpemFibGUtaW1hZ2UtY29udGFpbmVyXCIpKSB7XG4gICAgICAgICAgY29uc3QgaW1nID0gZG9tLnF1ZXJ5U2VsZWN0b3IoXCJpbWdcIik7XG4gICAgICAgICAgaWYgKGltZykge1xuICAgICAgICAgICAgcmV0dXJuIGltZy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRvbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChfZSkge1xuICAgICAgLy8gRmFsbGJhY2sgaWYgbm9kZURPTSBmYWlsc1xuICAgIH1cblxuICAgIC8vIDIuIFVsdGltYXRlIGZhbGxiYWNrOiBmaW5kIHNlbGVjdGVkIGltYWdlIGluIERPTVxuICAgIGNvbnN0IHNlbGVjdGVkSW1nID0gZWQudmlldy5kb20ucXVlcnlTZWxlY3RvcihcbiAgICAgIFwiaW1nLnNlbGVjdGVkLCAucmVzaXphYmxlLWltYWdlLWNvbnRhaW5lci5zZWxlY3RlZCBpbWdcIlxuICAgICk7XG4gICAgaWYgKHNlbGVjdGVkSW1nKSB7XG4gICAgICByZXR1cm4gc2VsZWN0ZWRJbWcuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgfVxuXG4gICAgLy8gSWYgbm90aGluZyBmb3VuZCBhdCBhbGxcbiAgICByZXR1cm4gbmV3IERPTVJlY3QoLTk5OTksIC05OTk5LCAwLCAwKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBleGVjdXRlQ29tbWFuZChlZGl0b3I6IEVkaXRvciwgY29tbWFuZDogc3RyaW5nLCAuLi5fYXJnczogdW5rbm93bltdKTogdm9pZCB7XG4gICAgc3dpdGNoIChjb21tYW5kKSB7XG4gICAgICBjYXNlIFwiY2hhbmdlSW1hZ2VcIjpcbiAgICAgICAgdGhpcy5jaGFuZ2VJbWFnZSgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJkb3dubG9hZEltYWdlXCI6XG4gICAgICAgIHRoaXMuZWRpdG9yQ29tbWFuZHMuZG93bmxvYWRJbWFnZShlZGl0b3IpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJyZXNpemVTbWFsbFwiOlxuICAgICAgICB0aGlzLmltYWdlU2VydmljZS5yZXNpemVJbWFnZVRvU21hbGwoZWRpdG9yKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwicmVzaXplTWVkaXVtXCI6XG4gICAgICAgIHRoaXMuaW1hZ2VTZXJ2aWNlLnJlc2l6ZUltYWdlVG9NZWRpdW0oZWRpdG9yKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwicmVzaXplTGFyZ2VcIjpcbiAgICAgICAgdGhpcy5pbWFnZVNlcnZpY2UucmVzaXplSW1hZ2VUb0xhcmdlKGVkaXRvcik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcInJlc2l6ZU9yaWdpbmFsXCI6XG4gICAgICAgIHRoaXMuaW1hZ2VTZXJ2aWNlLnJlc2l6ZUltYWdlVG9PcmlnaW5hbChlZGl0b3IpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJkZWxldGVJbWFnZVwiOlxuICAgICAgICB0aGlzLmRlbGV0ZUltYWdlKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcImFsaWduTGVmdFwiOlxuICAgICAgICBlZGl0b3IuY2hhaW4oKS5mb2N1cygpLnNldFRleHRBbGlnbihcImxlZnRcIikucnVuKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBcImFsaWduQ2VudGVyXCI6XG4gICAgICAgIGVkaXRvci5jaGFpbigpLmZvY3VzKCkuc2V0VGV4dEFsaWduKFwiY2VudGVyXCIpLnJ1bigpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJhbGlnblJpZ2h0XCI6XG4gICAgICAgIGVkaXRvci5jaGFpbigpLmZvY3VzKCkuc2V0VGV4dEFsaWduKFwicmlnaHRcIikucnVuKCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY2hhbmdlSW1hZ2UoKSB7XG4gICAgY29uc3QgZWQgPSB0aGlzLmVkaXRvcigpO1xuICAgIGlmICghZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgLy8gVXNlIGRlZGljYXRlZCBtZXRob2QgdG8gcmVwbGFjZSBhbiBleGlzdGluZyBpbWFnZVxuICAgICAgYXdhaXQgdGhpcy5pbWFnZVNlcnZpY2Uuc2VsZWN0QW5kUmVwbGFjZUltYWdlKGVkLCB0aGlzLmltYWdlVXBsb2FkKCkpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKHRoaXMuaTE4blNlcnZpY2UuaW1hZ2VVcGxvYWQoKS51cGxvYWRFcnJvciwgZXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZGVsZXRlSW1hZ2UoKSB7XG4gICAgY29uc3QgZWQgPSB0aGlzLmVkaXRvcigpO1xuICAgIGlmIChlZCkge1xuICAgICAgZWQuY2hhaW4oKS5mb2N1cygpLmRlbGV0ZVNlbGVjdGlvbigpLnJ1bigpO1xuICAgIH1cbiAgfVxufVxuIl19
@@ -0,0 +1,247 @@
1
+ import { Component, ChangeDetectionStrategy, viewChild, signal, effect, inject, } from "@angular/core";
2
+ import { FormsModule } from "@angular/forms";
3
+ import { AteButtonComponent } from "../../ui/ate-button.component";
4
+ import { AteLinkService } from "../../../services/ate-link.service";
5
+ import { AteSeparatorComponent } from "../../ui/ate-separator.component";
6
+ import { AteBaseSubBubbleMenu } from "../base/ate-base-sub-bubble-menu";
7
+ import * as i0 from "@angular/core";
8
+ import * as i1 from "@angular/forms";
9
+ export class AteLinkBubbleMenuComponent extends AteBaseSubBubbleMenu {
10
+ constructor() {
11
+ super();
12
+ this.linkSvc = inject(AteLinkService);
13
+ this.t = this.i18nService.bubbleMenu;
14
+ this.common = this.i18nService.common;
15
+ this.linkInput = viewChild("linkInput");
16
+ this.editUrl = signal("");
17
+ // Reactive effect for URL sync
18
+ effect(() => {
19
+ const state = this.state();
20
+ const isInteracting = this.linkSvc.isInteracting();
21
+ const currentLinkHref = state.marks.linkHref || "";
22
+ // SYNC LOGIC:
23
+ // If we are NOT currently typing (interacting),
24
+ // always keep the input in sync with the current editor selection.
25
+ if (!isInteracting) {
26
+ this.editUrl.set(currentLinkHref);
27
+ }
28
+ }, { allowSignalWrites: true });
29
+ }
30
+ onStateChange() {
31
+ this.linkSvc.editMode();
32
+ this.linkSvc.menuTrigger();
33
+ this.linkSvc.isInteracting();
34
+ }
35
+ shouldShow() {
36
+ const { selection, marks, isEditable, isFocused } = this.state();
37
+ if (!isEditable) {
38
+ return false;
39
+ }
40
+ // Show if explicitly in edit mode (from toolbar/bubble menu) or interacting with input
41
+ if (this.linkSvc.editMode() || this.linkSvc.isInteracting()) {
42
+ return true;
43
+ }
44
+ // Show if cursor is on an existing link (read/preview mode)
45
+ return isFocused && marks.link && selection.empty;
46
+ }
47
+ getSelectionRect() {
48
+ const trigger = this.linkSvc.menuTrigger();
49
+ const ed = this.editor();
50
+ if (!ed) {
51
+ return new DOMRect(0, 0, 0, 0);
52
+ }
53
+ // 1. If we have a stable trigger from service (toolbar or parent menu), anchor to it
54
+ if (trigger) {
55
+ const rect = trigger.getBoundingClientRect();
56
+ // Only use if it's still visible/in DOM (width > 0)
57
+ if (rect.width > 0) {
58
+ return rect;
59
+ }
60
+ }
61
+ // 2. Otherwise (bubble menu / relay), anchor to text selection
62
+ const { from } = ed.state.selection;
63
+ try {
64
+ const { node } = ed.view.domAtPos(from);
65
+ const element = node instanceof Element ? node : node.parentElement;
66
+ const linkElement = element?.closest("a");
67
+ if (linkElement) {
68
+ return linkElement.getBoundingClientRect();
69
+ }
70
+ }
71
+ catch (_e) {
72
+ /* ignore */
73
+ }
74
+ // Use native selection for multi-line accuracy
75
+ const selection = window.getSelection();
76
+ if (selection && selection.rangeCount > 0) {
77
+ const range = selection.getRangeAt(0);
78
+ const rect = range.getBoundingClientRect();
79
+ if (rect.width > 0 && rect.height > 0) {
80
+ return rect;
81
+ }
82
+ }
83
+ // Final fallback to coordinates at cursor
84
+ const { top, bottom, left, right } = ed.view.coordsAtPos(from);
85
+ return new DOMRect(left, top, right - left, bottom - top);
86
+ }
87
+ onTippyHide() {
88
+ // Clear trigger only AFTER the menu is hidden to maintain anchor stability during animation
89
+ this.linkSvc.done();
90
+ this.linkSvc.close();
91
+ }
92
+ currentUrl() {
93
+ return this.state().marks.linkHref || "";
94
+ }
95
+ onMouseDown(event) {
96
+ event.stopPropagation();
97
+ const target = event.target;
98
+ if (target.tagName !== "INPUT") {
99
+ event.preventDefault();
100
+ }
101
+ }
102
+ onFocus() {
103
+ this.linkSvc.setInteracting(true);
104
+ }
105
+ onBlur() {
106
+ setTimeout(() => {
107
+ this.linkSvc.setInteracting(false);
108
+ this.updateMenu();
109
+ }, 150);
110
+ }
111
+ onOpenLink(event) {
112
+ event.preventDefault();
113
+ event.stopPropagation();
114
+ const url = this.currentUrl();
115
+ if (url) {
116
+ window.open(url, "_blank", "noopener,noreferrer");
117
+ }
118
+ }
119
+ onRemove(event) {
120
+ event.preventDefault();
121
+ event.stopPropagation();
122
+ this.linkSvc.unsetLink(this.editor());
123
+ }
124
+ onApply(event) {
125
+ event.preventDefault();
126
+ event.stopPropagation();
127
+ const url = this.editUrl().trim();
128
+ if (url) {
129
+ this.linkSvc.setLink(this.editor(), url);
130
+ this.editUrl.set("");
131
+ this.linkSvc.setInteracting(false);
132
+ this.hideTippy();
133
+ }
134
+ else {
135
+ this.onRemove(event);
136
+ }
137
+ }
138
+ onCancel(event) {
139
+ event.preventDefault();
140
+ event.stopPropagation();
141
+ this.linkSvc.close();
142
+ this.hideTippy();
143
+ }
144
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteLinkBubbleMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
145
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "18.2.14", type: AteLinkBubbleMenuComponent, isStandalone: true, selector: "ate-link-bubble-menu", viewQueries: [{ propertyName: "linkInput", first: true, predicate: ["linkInput"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
146
+ <div
147
+ #menuRef
148
+ class="bubble-menu"
149
+ (mousedown)="onMouseDown($event)"
150
+ (click)="$event.stopPropagation()"
151
+ (keydown)="$event.stopPropagation()"
152
+ (keydown.escape)="onCancel($event)"
153
+ tabindex="-1"
154
+ role="dialog">
155
+ <div class="link-input-row">
156
+ <div class="url-input-container">
157
+ <span class="material-symbols-outlined icon-link">link</span>
158
+ <input
159
+ #linkInput
160
+ type="text"
161
+ class="url-field"
162
+ [placeholder]="t().linkUrl"
163
+ [ngModel]="editUrl()"
164
+ (ngModelChange)="editUrl.set($event)"
165
+ (focus)="onFocus()"
166
+ (blur)="onBlur()"
167
+ (keydown.enter)="onApply($event)"
168
+ (keydown.escape)="onCancel($event)" />
169
+ </div>
170
+
171
+ <div class="action-buttons">
172
+ <ate-button
173
+ icon="check"
174
+ [title]="common().apply"
175
+ color="var(--ate-primary)"
176
+ [disabled]="!editUrl().trim()"
177
+ (buttonClick)="onApply($event)"></ate-button>
178
+ <ate-button
179
+ icon="open_in_new"
180
+ [title]="t().openLink"
181
+ [disabled]="!currentUrl()"
182
+ (buttonClick)="onOpenLink($event)"></ate-button>
183
+ <ate-separator />
184
+ <ate-button
185
+ icon="link_off"
186
+ [title]="t().removeLink"
187
+ variant="danger"
188
+ [disabled]="!currentUrl()"
189
+ (buttonClick)="onRemove($event)"></ate-button>
190
+ </div>
191
+ </div>
192
+ </div>
193
+ `, isInline: true, styles: [".link-input-row{display:flex;align-items:center;gap:6px}.url-input-container{flex:1;display:flex;align-items:center;background:var(--ate-surface-secondary, #f8fafc);border:1px solid var(--ate-border, #e2e8f0);border-radius:8px;padding:0 10px;height:32px;transition:all .15s ease}.url-input-container:focus-within{border-color:var(--ate-primary, #3b82f6);background:var(--ate-surface, #ffffff);box-shadow:0 0 0 2px var(--ate-primary-light, rgba(59, 130, 246, .1))}.icon-link{font-size:16px;color:var(--ate-text-muted, #94a3b8);margin-right:6px}.url-field{background:transparent;border:none;outline:none;color:var(--ate-text, #1e293b);font-size:13px;width:100%;font-family:inherit}.action-buttons{display:flex;align-items:center;gap:2px}\n"], dependencies: [{ kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }, { kind: "component", type: AteSeparatorComponent, selector: "ate-separator" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
194
+ }
195
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteLinkBubbleMenuComponent, decorators: [{
196
+ type: Component,
197
+ args: [{ selector: "ate-link-bubble-menu", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [AteButtonComponent, AteSeparatorComponent, FormsModule], template: `
198
+ <div
199
+ #menuRef
200
+ class="bubble-menu"
201
+ (mousedown)="onMouseDown($event)"
202
+ (click)="$event.stopPropagation()"
203
+ (keydown)="$event.stopPropagation()"
204
+ (keydown.escape)="onCancel($event)"
205
+ tabindex="-1"
206
+ role="dialog">
207
+ <div class="link-input-row">
208
+ <div class="url-input-container">
209
+ <span class="material-symbols-outlined icon-link">link</span>
210
+ <input
211
+ #linkInput
212
+ type="text"
213
+ class="url-field"
214
+ [placeholder]="t().linkUrl"
215
+ [ngModel]="editUrl()"
216
+ (ngModelChange)="editUrl.set($event)"
217
+ (focus)="onFocus()"
218
+ (blur)="onBlur()"
219
+ (keydown.enter)="onApply($event)"
220
+ (keydown.escape)="onCancel($event)" />
221
+ </div>
222
+
223
+ <div class="action-buttons">
224
+ <ate-button
225
+ icon="check"
226
+ [title]="common().apply"
227
+ color="var(--ate-primary)"
228
+ [disabled]="!editUrl().trim()"
229
+ (buttonClick)="onApply($event)"></ate-button>
230
+ <ate-button
231
+ icon="open_in_new"
232
+ [title]="t().openLink"
233
+ [disabled]="!currentUrl()"
234
+ (buttonClick)="onOpenLink($event)"></ate-button>
235
+ <ate-separator />
236
+ <ate-button
237
+ icon="link_off"
238
+ [title]="t().removeLink"
239
+ variant="danger"
240
+ [disabled]="!currentUrl()"
241
+ (buttonClick)="onRemove($event)"></ate-button>
242
+ </div>
243
+ </div>
244
+ </div>
245
+ `, styles: [".link-input-row{display:flex;align-items:center;gap:6px}.url-input-container{flex:1;display:flex;align-items:center;background:var(--ate-surface-secondary, #f8fafc);border:1px solid var(--ate-border, #e2e8f0);border-radius:8px;padding:0 10px;height:32px;transition:all .15s ease}.url-input-container:focus-within{border-color:var(--ate-primary, #3b82f6);background:var(--ate-surface, #ffffff);box-shadow:0 0 0 2px var(--ate-primary-light, rgba(59, 130, 246, .1))}.icon-link{font-size:16px;color:var(--ate-text-muted, #94a3b8);margin-right:6px}.url-field{background:transparent;border:none;outline:none;color:var(--ate-text, #1e293b);font-size:13px;width:100%;font-family:inherit}.action-buttons{display:flex;align-items:center;gap:2px}\n"] }]
246
+ }], ctorParameters: () => [] });
247
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRlLWxpbmstYnViYmxlLW1lbnUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci10aXB0YXAtZWRpdG9yL3NyYy9saWIvY29tcG9uZW50cy9idWJibGUtbWVudXMvbGluay9hdGUtbGluay1idWJibGUtbWVudS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCx1QkFBdUIsRUFDdkIsU0FBUyxFQUVULE1BQU0sRUFDTixNQUFNLEVBQ04sTUFBTSxHQUNQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNuRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDcEUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDekUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7OztBQTBHeEUsTUFBTSxPQUFPLDBCQUEyQixTQUFRLG9CQUFvQjtJQVVsRTtRQUNFLEtBQUssRUFBRSxDQUFDO1FBVk8sWUFBTyxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUV6QyxNQUFDLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUM7UUFDaEMsV0FBTSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDO1FBRTFDLGNBQVMsR0FBRyxTQUFTLENBQStCLFdBQVcsQ0FBQyxDQUFDO1FBRWpFLFlBQU8sR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7UUFLbkIsK0JBQStCO1FBQy9CLE1BQU0sQ0FBQyxHQUFHLEVBQUU7WUFDVixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxF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LENBQUMsQ0FBQztZQUNuQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDbkIsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3ZCLENBQUM7SUFDSCxDQUFDO0lBRUQsUUFBUSxDQUFDLEtBQVk7UUFDbkIsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3ZCLEtBQUssQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUNuQixDQUFDOytHQTdKVSwwQkFBMEI7bUdBQTFCLDBCQUEwQiwrTkFuRzNCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnRFQsMnlCQWpEUyxrQkFBa0IsNkxBQUUscUJBQXFCLHlEQUFFLFdBQVc7OzRGQW9HckQsMEJBQTBCO2tCQXhHdEMsU0FBUzsrQkFDRSxzQkFBc0IsY0FDcEIsSUFBSSxtQkFDQyx1QkFBdUIsQ0FBQyxNQUFNLFdBQ3RDLENBQUMsa0JBQWtCLEVBQUUscUJBQXFCLEVBQUUsV0FBVyxDQUFDLFlBQ3ZEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnRFQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICB2aWV3Q2hpbGQsXG4gIEVsZW1lbnRSZWYsXG4gIHNpZ25hbCxcbiAgZWZmZWN0LFxuICBpbmplY3QsXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBGb3Jtc01vZHVsZSB9IGZyb20gXCJAYW5ndWxhci9mb3Jtc1wiO1xuaW1wb3J0IHsgQXRlQnV0dG9uQ29tcG9uZW50IH0gZnJvbSBcIi4uLy4uL3VpL2F0ZS1idXR0b24uY29tcG9uZW50XCI7XG5pbXBvcnQgeyBBdGVMaW5rU2VydmljZSB9IGZyb20gXCIuLi8uLi8uLi9zZXJ2aWNlcy9hdGUtbGluay5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBBdGVTZXBhcmF0b3JDb21wb25lbnQgfSBmcm9tIFwiLi4vLi4vdWkvYXRlLXNlcGFyYXRvci5jb21wb25lbnRcIjtcbmltcG9ydCB7IEF0ZUJhc2VTdWJCdWJibGVNZW51IH0gZnJvbSBcIi4uL2Jhc2UvYXRlLWJhc2Utc3ViLWJ1YmJsZS1tZW51XCI7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogXCJhdGUtbGluay1idWJibGUtbWVudVwiLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgaW1wb3J0czogW0F0ZUJ1dHRvbkNvbXBvbmVudCwgQXRlU2VwYXJhdG9yQ29tcG9uZW50LCBGb3Jtc01vZHVsZV0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdlxuICAgICAgI21lbnVSZWZcbiAgICAgIGNsYXNzPVwiYnViYmxlLW1lbnVcIlxuICAgICAgKG1vdXNlZG93bik9XCJvbk1vdXNlRG93bigkZXZlbnQpXCJcbiAgICAgIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxuICAgICAgKGtleWRvd24pPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcbiAgICAgIChrZXlkb3duLmVzY2FwZSk9XCJvbkNhbmNlbCgkZXZlbnQpXCJcbiAgICAgIHRhYmluZGV4PVwiLTFcIlxuICAgICAgcm9sZT1cImRpYWxvZ1wiPlxuICAgICAgPGRpdiBjbGFzcz1cImxpbmstaW5wdXQtcm93XCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJ1cmwtaW5wdXQtY29udGFpbmVyXCI+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJtYXRlcmlhbC1zeW1ib2xzLW91dGxpbmVkIGljb24tbGlua1wiPmxpbms8L3NwYW4+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAjbGlua0lucHV0XG4gICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICBjbGFzcz1cInVybC1maWVsZFwiXG4gICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwidCgpLmxpbmtVcmxcIlxuICAgICAgICAgICAgW25nTW9kZWxdPVwiZWRpdFVybCgpXCJcbiAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cImVkaXRVcmwuc2V0KCRldmVudClcIlxuICAgICAgICAgICAgKGZvY3VzKT1cIm9uRm9jdXMoKVwiXG4gICAgICAgICAgICAoYmx1cik9XCJvbkJsdXIoKVwiXG4gICAgICAgICAgICAoa2V5ZG93bi5lbnRlcik9XCJvbkFwcGx5KCRldmVudClcIlxuICAgICAgICAgICAgKGtleWRvd24uZXNjYXBlKT1cIm9uQ2FuY2VsKCRldmVudClcIiAvPlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiYWN0aW9uLWJ1dHRvbnNcIj5cbiAgICAgICAgICA8YXRlLWJ1dHRvblxuICAgICAgICAgICAgaWNvbj1cImNoZWNrXCJcbiAgICAgICAgICAgIFt0aXRsZV09XCJjb21tb24oKS5hcHBseVwiXG4gICAgICAgICAgICBjb2xvcj1cInZhcigtLWF0ZS1wcmltYXJ5KVwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiIWVkaXRVcmwoKS50cmltKClcIlxuICAgICAgICAgICAgKGJ1dHRvbkNsaWNrKT1cIm9uQXBwbHkoJGV2ZW50KVwiPjwvYXRlLWJ1dHRvbj5cbiAgICAgICAgICA8YXRlLWJ1dHRvblxuICAgICAgICAgICAgaWNvbj1cIm9wZW5faW5fbmV3XCJcbiAgICAgICAgICAgIFt0aXRsZV09XCJ0KCkub3BlbkxpbmtcIlxuICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFjdXJyZW50VXJsKClcIlxuICAgICAgICAgICAgKGJ1dHRvbkNsaWNrKT1cIm9uT3BlbkxpbmsoJGV2ZW50KVwiPjwvYXRlLWJ1dHRvbj5cbiAgICAgICAgICA8YXRlLXNlcGFyYXRvciAvPlxuICAgICAgICAgIDxhdGUtYnV0dG9uXG4gICAgICAgICAgICBpY29uPVwibGlua19vZmZcIlxuICAgICAgICAgICAgW3RpdGxlXT1cInQoKS5yZW1vdmVMaW5rXCJcbiAgICAgICAgICAgIHZhcmlhbnQ9XCJkYW5nZXJcIlxuICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFjdXJyZW50VXJsKClcIlxuICAgICAgICAgICAgKGJ1dHRvbkNsaWNrKT1cIm9uUmVtb3ZlKCRldmVudClcIj48L2F0ZS1idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIGAsXG4gIHN0eWxlczogW1xuICAgIGBcbiAgICAgIC5saW5rLWlucHV0LXJvdyB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICAgIGdhcDogNnB4O1xuICAgICAgfVxuXG4gICAgICAudXJsLWlucHV0LWNvbnRhaW5lciB7XG4gICAgICAgIGZsZXg6IDE7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICAgIGJhY2tncm91bmQ6IHZhcigtLWF0ZS1zdXJmYWNlLXNlY29uZGFyeSwgI2Y4ZmFmYyk7XG4gICAgICAgIGJvcmRlcjogMXB4IHNvbGlkIHZhcigtLWF0ZS1ib3JkZXIsICNlMmU4ZjApO1xuICAgICAgICBib3JkZXItcmFkaXVzOiA4cHg7XG4gICAgICAgIHBhZGRpbmc6IDAgMTBweDtcbiAgICAgICAgaGVpZ2h0OiAzMnB4O1xuICAgICAgICB0cmFuc2l0aW9uOiBhbGwgMTUwbXMgZWFzZTtcbiAgICAgIH1cblxuICAgICAgLnVybC1pbnB1dC1jb250YWluZXI6Zm9jdXMtd2l0aGluIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB2YXIoLS1hdGUtcHJpbWFyeSwgIzNiODJmNik7XG4gICAgICAgIGJhY2tncm91bmQ6IHZhcigtLWF0ZS1zdXJmYWNlLCAjZmZmZmZmKTtcbiAgICAgICAgYm94LXNoYWRvdzogMCAwIDAgMnB4IHZhcigtLWF0ZS1wcmltYXJ5LWxpZ2h0LCByZ2JhKDU5LCAxMzAsIDI0NiwgMC4xKSk7XG4gICAgICB9XG5cbiAgICAgIC5pY29uLWxpbmsge1xuICAgICAgICBmb250LXNpemU6IDE2cHg7XG4gICAgICAgIGNvbG9yOiB2YXIoLS1hdGUtdGV4dC1tdXRlZCwgIzk0YTNiOCk7XG4gICAgICAgIG1hcmdpbi1yaWdodDogNnB4O1xuICAgICAgfVxuXG4gICAgICAudXJsLWZpZWxkIHtcbiAgICAgICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XG4gICAgICAgIGJvcmRlcjogbm9uZTtcbiAgICAgICAgb3V0bGluZTogbm9uZTtcbiAgICAgICAgY29sb3I6IHZhcigtLWF0ZS10ZXh0LCAjMWUyOTNiKTtcbiAgICAgICAgZm9udC1zaXplOiAxM3B4O1xuICAgICAgICB3aWR0aDogMTAwJTtcbiAgICAgICAgZm9udC1mYW1pbHk6IGluaGVyaXQ7XG4gICAgICB9XG5cbiAgICAgIC5hY3Rpb24tYnV0dG9ucyB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICAgIGdhcDogMnB4O1xuICAgICAgfVxuICAgIGAsXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIEF0ZUxpbmtCdWJibGVNZW51Q29tcG9uZW50IGV4dGVuZHMgQXRlQmFzZVN1YkJ1YmJsZU1lbnUge1xuICBwcml2YXRlIHJlYWRvbmx5IGxpbmtTdmMgPSBpbmplY3QoQXRlTGlua1NlcnZpY2UpO1xuXG4gIHJlYWRvbmx5IHQgPSB0aGlzLmkxOG5TZXJ2aWNlLmJ1YmJsZU1lbnU7XG4gIHJlYWRvbmx5IGNvbW1vbiA9IHRoaXMuaTE4blNlcnZpY2UuY29tbW9uO1xuXG4gIGxpbmtJbnB1dCA9IHZpZXdDaGlsZDxFbGVtZW50UmVmPEhUTUxJbnB1dEVsZW1lbnQ+PihcImxpbmtJbnB1dFwiKTtcblxuICBlZGl0VXJsID0gc2lnbmFsKFwiXCIpO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICAvLyBSZWFjdGl2ZSBlZmZlY3QgZm9yIFVSTCBzeW5jXG4gICAgZWZmZWN0KCgpID0+IHtcbiAgICAgIGNvbnN0IHN0YXRlID0gdGhpcy5zdGF0ZSgpO1xuICAgICAgY29uc3QgaXNJbnRlcmFjdGluZyA9IHRoaXMubGlua1N2Yy5pc0ludGVyYWN0aW5nKCk7XG4gICAgICBjb25zdCBjdXJyZW50TGlua0hyZWYgPSBzdGF0ZS5tYXJrcy5saW5rSHJlZiB8fCBcIlwiO1xuXG4gICAgICAvLyBTWU5DIExPR0lDOlxuICAgICAgLy8gSWYgd2UgYXJlIE5PVCBjdXJyZW50bHkgdHlwaW5nIChpbnRlcmFjdGluZyksXG4gICAgICAvLyBhbHdheXMga2VlcCB0aGUgaW5wdXQgaW4gc3luYyB3aXRoIHRoZSBjdXJyZW50IGVkaXRvciBzZWxlY3Rpb24uXG4gICAgICBpZiAoIWlzSW50ZXJhY3RpbmcpIHtcbiAgICAgICAgdGhpcy5lZGl0VXJsLnNldChjdXJyZW50TGlua0hyZWYpO1xuICAgICAgfVxuICAgIH0sIHsgYWxsb3dTaWduYWxXcml0ZXM6IHRydWUgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgb25TdGF0ZUNoYW5nZSgpIHtcbiAgICB0aGlzLmxpbmtTdmMuZWRpdE1vZGUoKTtcbiAgICB0aGlzLmxpbmtTdmMubWVudVRyaWdnZXIoKTtcbiAgICB0aGlzLmxpbmtTdmMuaXNJbnRlcmFjdGluZygpO1xuICB9XG5cbiAgb3ZlcnJpZGUgc2hvdWxkU2hvdygpOiBib29sZWFuIHtcbiAgICBjb25zdCB7IHNlbGVjdGlvbiwgbWFya3MsIGlzRWRpdGFibGUsIGlzRm9jdXNlZCB9ID0gdGhpcy5zdGF0ZSgpO1xuICAgIGlmICghaXNFZGl0YWJsZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIFNob3cgaWYgZXhwbGljaXRseSBpbiBlZGl0IG1vZGUgKGZyb20gdG9vbGJhci9idWJibGUgbWVudSkgb3IgaW50ZXJhY3Rpbmcgd2l0aCBpbnB1dFxuICAgIGlmICh0aGlzLmxpbmtTdmMuZWRpdE1vZGUoKSB8fCB0aGlzLmxpbmtTdmMuaXNJbnRlcmFjdGluZygpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBTaG93IGlmIGN1cnNvciBpcyBvbiBhbiBleGlzdGluZyBsaW5rIChyZWFkL3ByZXZpZXcgbW9kZSlcbiAgICByZXR1cm4gaXNGb2N1c2VkICYmIG1hcmtzLmxpbmsgJiYgc2VsZWN0aW9uLmVtcHR5O1xuICB9XG5cbiAgb3ZlcnJpZGUgZ2V0U2VsZWN0aW9uUmVjdCgpOiBET01SZWN0IHtcbiAgICBjb25zdCB0cmlnZ2VyID0gdGhpcy5saW5rU3ZjLm1lbnVUcmlnZ2VyKCk7XG4gICAgY29uc3QgZWQgPSB0aGlzLmVkaXRvcigpO1xuICAgIGlmICghZWQpIHtcbiAgICAgIHJldHVybiBuZXcgRE9NUmVjdCgwLCAwLCAwLCAwKTtcbiAgICB9XG5cbiAgICAvLyAxLiBJZiB3ZSBoYXZlIGEgc3RhYmxlIHRyaWdnZXIgZnJvbSBzZXJ2aWNlICh0b29sYmFyIG9yIHBhcmVudCBtZW51KSwgYW5jaG9yIHRvIGl0XG4gICAgaWYgKHRyaWdnZXIpIHtcbiAgICAgIGNvbnN0IHJlY3QgPSB0cmlnZ2VyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgLy8gT25seSB1c2UgaWYgaXQncyBzdGlsbCB2aXNpYmxlL2luIERPTSAod2lkdGggPiAwKVxuICAgICAgaWYgKHJlY3Qud2lkdGggPiAwKSB7XG4gICAgICAgIHJldHVybiByZWN0O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIDIuIE90aGVyd2lzZSAoYnViYmxlIG1lbnUgLyByZWxheSksIGFuY2hvciB0byB0ZXh0IHNlbGVjdGlvblxuICAgIGNvbnN0IHsgZnJvbSB9ID0gZWQuc3RhdGUuc2VsZWN0aW9uO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgbm9kZSB9ID0gZWQudmlldy5kb21BdFBvcyhmcm9tKTtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSBub2RlIGluc3RhbmNlb2YgRWxlbWVudCA/IG5vZGUgOiBub2RlLnBhcmVudEVsZW1lbnQ7XG4gICAgICBjb25zdCBsaW5rRWxlbWVudCA9IChlbGVtZW50IGFzIEVsZW1lbnQpPy5jbG9zZXN0KFwiYVwiKTtcbiAgICAgIGlmIChsaW5rRWxlbWVudCkge1xuICAgICAgICByZXR1cm4gbGlua0VsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoX2UpIHtcbiAgICAgIC8qIGlnbm9yZSAqL1xuICAgIH1cblxuICAgIC8vIFVzZSBuYXRpdmUgc2VsZWN0aW9uIGZvciBtdWx0aS1saW5lIGFjY3VyYWN5XG4gICAgY29uc3Qgc2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgIGlmIChzZWxlY3Rpb24gJiYgc2VsZWN0aW9uLnJhbmdlQ291bnQgPiAwKSB7XG4gICAgICBjb25zdCByYW5nZSA9IHNlbGVjdGlvbi5nZXRSYW5nZUF0KDApO1xuICAgICAgY29uc3QgcmVjdCA9IHJhbmdlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgaWYgKHJlY3Qud2lkdGggPiAwICYmIHJlY3QuaGVpZ2h0ID4gMCkge1xuICAgICAgICByZXR1cm4gcmVjdDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBGaW5hbCBmYWxsYmFjayB0byBjb29yZGluYXRlcyBhdCBjdXJzb3JcbiAgICBjb25zdCB7IHRvcCwgYm90dG9tLCBsZWZ0LCByaWdodCB9ID0gZWQudmlldy5jb29yZHNBdFBvcyhmcm9tKTtcbiAgICByZXR1cm4gbmV3IERPTVJlY3QobGVmdCwgdG9wLCByaWdodCAtIGxlZnQsIGJvdHRvbSAtIHRvcCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgb25UaXBweUhpZGUoKSB7XG4gICAgLy8gQ2xlYXIgdHJpZ2dlciBvbmx5IEFGVEVSIHRoZSBtZW51IGlzIGhpZGRlbiB0byBtYWludGFpbiBhbmNob3Igc3RhYmlsaXR5IGR1cmluZyBhbmltYXRpb25cbiAgICB0aGlzLmxpbmtTdmMuZG9uZSgpO1xuICAgIHRoaXMubGlua1N2Yy5jbG9zZSgpO1xuICB9XG5cbiAgY3VycmVudFVybCgpIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZSgpLm1hcmtzLmxpbmtIcmVmIHx8IFwiXCI7XG4gIH1cblxuICBvbk1vdXNlRG93bihldmVudDogTW91c2VFdmVudCkge1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudDtcbiAgICBpZiAodGFyZ2V0LnRhZ05hbWUgIT09IFwiSU5QVVRcIikge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG4gIH1cblxuICBvbkZvY3VzKCkge1xuICAgIHRoaXMubGlua1N2Yy5zZXRJbnRlcmFjdGluZyh0cnVlKTtcbiAgfVxuXG4gIG9uQmx1cigpIHtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMubGlua1N2Yy5zZXRJbnRlcmFjdGluZyhmYWxzZSk7XG4gICAgICB0aGlzLnVwZGF0ZU1lbnUoKTtcbiAgICB9LCAxNTApO1xuICB9XG5cbiAgb25PcGVuTGluayhldmVudDogRXZlbnQpIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIGNvbnN0IHVybCA9IHRoaXMuY3VycmVudFVybCgpO1xuICAgIGlmICh1cmwpIHtcbiAgICAgIHdpbmRvdy5vcGVuKHVybCwgXCJfYmxhbmtcIiwgXCJub29wZW5lcixub3JlZmVycmVyXCIpO1xuICAgIH1cbiAgfVxuXG4gIG9uUmVtb3ZlKGV2ZW50OiBFdmVudCkge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgdGhpcy5saW5rU3ZjLnVuc2V0TGluayh0aGlzLmVkaXRvcigpKTtcbiAgfVxuXG4gIG9uQXBwbHkoZXZlbnQ6IEV2ZW50KSB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICBjb25zdCB1cmwgPSB0aGlzLmVkaXRVcmwoKS50cmltKCk7XG4gICAgaWYgKHVybCkge1xuICAgICAgdGhpcy5saW5rU3ZjLnNldExpbmsodGhpcy5lZGl0b3IoKSwgdXJsKTtcbiAgICAgIHRoaXMuZWRpdFVybC5zZXQoXCJcIik7XG4gICAgICB0aGlzLmxpbmtTdmMuc2V0SW50ZXJhY3RpbmcoZmFsc2UpO1xuICAgICAgdGhpcy5oaWRlVGlwcHkoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vblJlbW92ZShldmVudCk7XG4gICAgfVxuICB9XG5cbiAgb25DYW5jZWwoZXZlbnQ6IEV2ZW50KSB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLmxpbmtTdmMuY2xvc2UoKTtcbiAgICB0aGlzLmhpZGVUaXBweSgpO1xuICB9XG59XG4iXX0=