@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,459 @@
1
+ import { Injectable, signal, computed, inject } from "@angular/core";
2
+ import { isObservable, firstValueFrom } from "rxjs";
3
+ import { AteI18nService } from "./ate-i18n.service";
4
+ import * as i0 from "@angular/core";
5
+ export class AteImageService {
6
+ constructor() {
7
+ /** Signals for image state */
8
+ this.selectedImage = signal(null);
9
+ this.isImageSelected = computed(() => this.selectedImage() !== null);
10
+ /** Resizing state */
11
+ this.isResizing = signal(false);
12
+ this.i18n = inject(AteI18nService);
13
+ this.t = this.i18n.imageUpload;
14
+ /** Upload state signals */
15
+ this.isUploading = signal(false);
16
+ this.uploadProgress = signal(0);
17
+ this.uploadMessage = signal("");
18
+ /**
19
+ * Custom upload handler.
20
+ * If set, this handler replaces the default base64 conversion.
21
+ */
22
+ this.uploadHandler = null;
23
+ this.currentEditor = null;
24
+ }
25
+ /** Select and track an image from the editor */
26
+ selectImage(editor) {
27
+ if (editor.isActive("resizableImage")) {
28
+ const attrs = editor.getAttributes("resizableImage");
29
+ this.selectedImage.set({
30
+ src: attrs["src"],
31
+ alt: attrs["alt"],
32
+ title: attrs["title"],
33
+ width: attrs["width"],
34
+ height: attrs["height"],
35
+ });
36
+ }
37
+ else {
38
+ this.selectedImage.set(null);
39
+ }
40
+ }
41
+ clearSelection() {
42
+ this.selectedImage.set(null);
43
+ }
44
+ /** Insert a new image and ensure it's selected */
45
+ insertImage(editor, imageData) {
46
+ editor
47
+ .chain()
48
+ .focus()
49
+ .setResizableImage(imageData)
50
+ .command(({ tr, commands }) => {
51
+ // Selection is usually after the node. Node is at tr.selection.from - 1.
52
+ const { from } = tr.selection;
53
+ // Try to select node at current pos (if it was already selected) or previous pos
54
+ return commands.setNodeSelection(from) || commands.setNodeSelection(from - 1) || true;
55
+ })
56
+ .run();
57
+ }
58
+ /** Update attributes of the currently active image */
59
+ updateImageAttributes(editor, attributes) {
60
+ if (editor.isActive("resizableImage")) {
61
+ const pos = editor.state.selection.from;
62
+ editor
63
+ .chain()
64
+ .focus()
65
+ .updateAttributes("resizableImage", attributes)
66
+ .setNodeSelection(pos)
67
+ .run();
68
+ this.updateSelectedImage(attributes);
69
+ }
70
+ }
71
+ /** Resize image with optional aspect ratio maintenance */
72
+ resizeImage(editor, options) {
73
+ if (!editor.isActive("resizableImage")) {
74
+ return;
75
+ }
76
+ const currentAttrs = editor.getAttributes("resizableImage");
77
+ let newWidth = options.width;
78
+ let newHeight = options.height;
79
+ // Maintain aspect ratio if requested
80
+ if (options.maintainAspectRatio !== false && currentAttrs["width"] && currentAttrs["height"]) {
81
+ const aspectRatio = currentAttrs["width"] / currentAttrs["height"];
82
+ if (newWidth && !newHeight) {
83
+ newHeight = Math.round(newWidth / aspectRatio);
84
+ }
85
+ else if (newHeight && !newWidth) {
86
+ newWidth = Math.round(newHeight * aspectRatio);
87
+ }
88
+ }
89
+ // Apply minimum limits
90
+ if (newWidth) {
91
+ newWidth = Math.max(50, newWidth);
92
+ }
93
+ if (newHeight) {
94
+ newHeight = Math.max(50, newHeight);
95
+ }
96
+ this.updateImageAttributes(editor, {
97
+ width: newWidth,
98
+ height: newHeight,
99
+ });
100
+ }
101
+ /** Predetermined resize helpers used by UI */
102
+ resizeImageToSmall(editor) {
103
+ this.resizeImage(editor, { width: 300, height: 200, maintainAspectRatio: true });
104
+ }
105
+ resizeImageToMedium(editor) {
106
+ this.resizeImage(editor, { width: 500, height: 350, maintainAspectRatio: true });
107
+ }
108
+ resizeImageToLarge(editor) {
109
+ this.resizeImage(editor, { width: 800, height: 600, maintainAspectRatio: true });
110
+ }
111
+ resizeImageToOriginal(editor) {
112
+ if (!editor.isActive("resizableImage")) {
113
+ return;
114
+ }
115
+ const img = new Image();
116
+ img.onload = () => {
117
+ this.resizeImage(editor, { width: img.naturalWidth, height: img.naturalHeight });
118
+ };
119
+ img.src = editor.getAttributes("resizableImage")["src"];
120
+ }
121
+ /** Get current image dimensions */
122
+ getImageDimensions(editor) {
123
+ if (!editor.isActive("resizableImage")) {
124
+ return null;
125
+ }
126
+ const attrs = editor.getAttributes("resizableImage");
127
+ return {
128
+ width: attrs["width"] || 0,
129
+ height: attrs["height"] || 0,
130
+ };
131
+ }
132
+ /** Remove the selected image */
133
+ deleteImage(editor) {
134
+ if (editor.isActive("resizableImage")) {
135
+ editor.chain().focus().deleteSelection().run();
136
+ this.clearSelection();
137
+ }
138
+ }
139
+ /** Download the current image */
140
+ downloadImage(editor) {
141
+ const attrs = editor.getAttributes("resizableImage");
142
+ if (!attrs || !attrs["src"]) {
143
+ return;
144
+ }
145
+ const src = attrs["src"];
146
+ const fileName = attrs["alt"] || "image";
147
+ // Detect if it's base64 or remote URL
148
+ if (src.startsWith("data:") ||
149
+ src.startsWith("blob:") ||
150
+ src.startsWith(window.location.origin)) {
151
+ const link = document.createElement("a");
152
+ link.href = src;
153
+ link.download = fileName;
154
+ document.body.appendChild(link);
155
+ link.click();
156
+ document.body.removeChild(link);
157
+ }
158
+ else {
159
+ // For remote URLs, we try to fetch it to bypass cross-origin restrictions on 'download' attribute
160
+ fetch(src)
161
+ .then(response => response.blob())
162
+ .then(blob => {
163
+ const url = window.URL.createObjectURL(blob);
164
+ const link = document.createElement("a");
165
+ link.href = url;
166
+ link.download = fileName;
167
+ document.body.appendChild(link);
168
+ link.click();
169
+ document.body.removeChild(link);
170
+ window.URL.revokeObjectURL(url);
171
+ })
172
+ .catch(err => {
173
+ console.error("Error downloading image:", err);
174
+ // Fallback to opening in new tab
175
+ window.open(src, "_blank");
176
+ });
177
+ }
178
+ }
179
+ updateSelectedImage(attributes) {
180
+ const current = this.selectedImage();
181
+ if (current) {
182
+ this.selectedImage.set({ ...current, ...attributes });
183
+ }
184
+ }
185
+ /** Validate file type and size */
186
+ validateImage(file, options) {
187
+ const maxSize = options?.maxSize || 10 * 1024 * 1024;
188
+ const allowedTypes = options?.allowedTypes || [];
189
+ if (allowedTypes.length > 0 && !allowedTypes.includes(file.type)) {
190
+ return { valid: false, error: this.t().invalidFileType };
191
+ }
192
+ if (file.size > maxSize) {
193
+ return {
194
+ valid: false,
195
+ error: `${this.t().imageTooLarge} (max ${Math.round(maxSize / 1024 / 1024)}MB)`,
196
+ };
197
+ }
198
+ return { valid: true };
199
+ }
200
+ /** Compress and process image on client side */
201
+ async compressImage(file, quality = 0.8, maxWidth = 1920, maxHeight = 1200) {
202
+ return new Promise((resolve, reject) => {
203
+ const canvas = document.createElement("canvas");
204
+ const ctx = canvas.getContext("2d");
205
+ const img = new Image();
206
+ img.onload = () => {
207
+ if (this.isUploading()) {
208
+ this.uploadProgress.set(40);
209
+ this.uploadMessage.set(this.t().resizing);
210
+ }
211
+ let { width, height } = img;
212
+ if (width > maxWidth || height > maxHeight) {
213
+ const ratio = Math.min(maxWidth / width, maxHeight / height);
214
+ width *= ratio;
215
+ height *= ratio;
216
+ }
217
+ canvas.width = width;
218
+ canvas.height = height;
219
+ ctx?.drawImage(img, 0, 0, width, height);
220
+ if (this.isUploading()) {
221
+ this.uploadProgress.set(60);
222
+ this.uploadMessage.set(this.t().compressing);
223
+ }
224
+ canvas.toBlob(blob => {
225
+ if (blob) {
226
+ const reader = new FileReader();
227
+ reader.onload = e => {
228
+ const base64 = e.target?.result;
229
+ resolve({
230
+ src: base64,
231
+ name: file.name,
232
+ size: blob.size,
233
+ type: file.type,
234
+ width: Math.round(width),
235
+ height: Math.round(height),
236
+ originalSize: file.size,
237
+ });
238
+ };
239
+ reader.readAsDataURL(blob);
240
+ }
241
+ else {
242
+ reject(new Error(this.t().compressionError));
243
+ }
244
+ }, file.type, quality);
245
+ };
246
+ img.onerror = () => reject(new Error(this.t().loadError));
247
+ img.src = URL.createObjectURL(file);
248
+ });
249
+ }
250
+ /** Core upload logic with progress tracking */
251
+ async uploadImageWithProgress(editor, file, insertionStrategy, actionMessage, options) {
252
+ try {
253
+ this.currentEditor = editor;
254
+ this.isUploading.set(true);
255
+ this.uploadProgress.set(10);
256
+ this.uploadMessage.set(this.t().validating);
257
+ this.forceEditorUpdate();
258
+ const validation = this.validateImage(file, {
259
+ maxSize: options?.maxSize,
260
+ allowedTypes: options?.allowedTypes,
261
+ });
262
+ if (!validation.valid) {
263
+ throw new Error(validation.error);
264
+ }
265
+ this.uploadProgress.set(30);
266
+ this.uploadMessage.set(this.t().compressing);
267
+ this.forceEditorUpdate();
268
+ const result = await this.compressImage(file, options?.quality || 0.8, options?.maxWidth || 1920, options?.maxHeight || 1200);
269
+ this.uploadProgress.set(70);
270
+ // Handle custom upload if handler is provided
271
+ if (this.uploadHandler) {
272
+ this.uploadMessage.set(this.t().uploadingToServer);
273
+ this.forceEditorUpdate();
274
+ try {
275
+ const handlerResponse = this.uploadHandler({
276
+ file,
277
+ width: result.width || 0,
278
+ height: result.height || 0,
279
+ type: result.type,
280
+ base64: result.src,
281
+ });
282
+ const handlerResult = isObservable(handlerResponse)
283
+ ? await firstValueFrom(handlerResponse)
284
+ : await handlerResponse;
285
+ result.src = handlerResult.src;
286
+ if (handlerResult.alt) {
287
+ result.name = handlerResult.alt;
288
+ }
289
+ }
290
+ catch (handlerError) {
291
+ console.error(this.t().uploadError, handlerError);
292
+ throw handlerError;
293
+ }
294
+ }
295
+ this.uploadProgress.set(90);
296
+ this.uploadMessage.set(actionMessage);
297
+ this.forceEditorUpdate();
298
+ // Final insertion
299
+ insertionStrategy(editor, result);
300
+ this.resetUploadState();
301
+ }
302
+ catch (error) {
303
+ this.resetUploadState();
304
+ console.error(this.t().uploadError, error);
305
+ throw error;
306
+ }
307
+ }
308
+ resetUploadState() {
309
+ this.isUploading.set(false);
310
+ this.uploadProgress.set(0);
311
+ this.uploadMessage.set("");
312
+ this.forceEditorUpdate();
313
+ this.currentEditor = null;
314
+ }
315
+ /** Main entry point for file upload and insertion */
316
+ async uploadAndInsertImage(editor, file, options) {
317
+ return this.uploadImageWithProgress(editor, file, (ed, result) => {
318
+ this.insertImage(ed, {
319
+ src: result.src,
320
+ alt: result.name,
321
+ title: `${result.name} (${result.width}×${result.height})`,
322
+ width: result.width,
323
+ height: result.height,
324
+ });
325
+ }, this.t().insertingImage, options);
326
+ }
327
+ /** Trigger an editor transaction to force decoration update */
328
+ forceEditorUpdate() {
329
+ if (this.currentEditor) {
330
+ const { tr } = this.currentEditor.state;
331
+ this.currentEditor.view.dispatch(tr);
332
+ }
333
+ }
334
+ /** Generic helper to open file picker and process selection */
335
+ async selectFileAndProcess(editor, uploadMethod, options) {
336
+ return new Promise((resolve, reject) => {
337
+ const input = document.createElement("input");
338
+ input.type = "file";
339
+ // Use allowedTypes if provided, otherwise default to image/*
340
+ if (options?.allowedTypes && options.allowedTypes.length > 0) {
341
+ input.accept = options.allowedTypes.join(",");
342
+ }
343
+ else {
344
+ input.accept = "image/*";
345
+ }
346
+ input.style.display = "none";
347
+ input.addEventListener("change", async (e) => {
348
+ const file = e.target.files?.[0];
349
+ if (file && file.type.startsWith("image/")) {
350
+ try {
351
+ await uploadMethod(editor, file, options);
352
+ resolve();
353
+ }
354
+ catch (error) {
355
+ reject(error);
356
+ }
357
+ }
358
+ else {
359
+ reject(new Error(this.t().noFileSelected));
360
+ }
361
+ document.body.removeChild(input);
362
+ });
363
+ input.addEventListener("cancel", () => {
364
+ document.body.removeChild(input);
365
+ reject(new Error(this.t().selectionCancelled));
366
+ });
367
+ document.body.appendChild(input);
368
+ input.click();
369
+ });
370
+ }
371
+ /** Select file and upload as new image */
372
+ async selectAndUploadImage(editor, options) {
373
+ return this.selectFileAndProcess(editor, this.uploadAndInsertImage.bind(this), options);
374
+ }
375
+ /** Select file and replace currently selected image */
376
+ async selectAndReplaceImage(editor, options) {
377
+ // No need for complicated backup/restore now that we don't delete prematurely.
378
+ // The uploadAndReplaceImage will handle the atomic replacement.
379
+ return this.selectFileAndProcess(editor, this.uploadAndReplaceImage.bind(this), options);
380
+ }
381
+ /** Internal helper used by replacement logic */
382
+ async uploadAndReplaceImage(editor, file, options) {
383
+ // Store current position to ensure we can re-select the image even if selection blurs during upload
384
+ const wasActive = editor.isActive("resizableImage");
385
+ await this.uploadImageWithProgress(editor, file, (ed, result) => {
386
+ const imageData = {
387
+ src: result.src,
388
+ alt: result.name,
389
+ title: `${result.name} (${result.width}×${result.height})`,
390
+ width: result.width,
391
+ height: result.height,
392
+ };
393
+ // If the image was active or is still active, update it atomically
394
+ if (wasActive || ed.isActive("resizableImage")) {
395
+ ed.chain()
396
+ .focus()
397
+ .updateAttributes("resizableImage", imageData)
398
+ .command(({ tr, commands }) => {
399
+ const { from } = tr.selection;
400
+ // Re-select the node at its mapped position or current selection
401
+ return commands.setNodeSelection(from) || commands.setNodeSelection(from - 1) || true;
402
+ })
403
+ .run();
404
+ this.updateSelectedImage(imageData);
405
+ }
406
+ else {
407
+ // Otherwise replace whatever is selected (or insert at cursor)
408
+ this.insertImage(ed, imageData);
409
+ }
410
+ // After replacement, ensure the image is tracked in our signals
411
+ this.selectImage(ed);
412
+ }, this.t().replacingImage, options);
413
+ }
414
+ /**
415
+ * Handle image drop event.
416
+ * Calculates the position from coordinates and sets the selection accordingly.
417
+ */
418
+ handleDrop(editor, event, options) {
419
+ const files = event.dataTransfer?.files;
420
+ if (!files || files.length === 0) {
421
+ return false;
422
+ }
423
+ const file = Array.from(files).find(f => f.type.startsWith("image/"));
424
+ if (!file) {
425
+ return false;
426
+ }
427
+ event.preventDefault();
428
+ event.stopPropagation();
429
+ // Try to find the drop position from coordinates
430
+ const pos = editor.view.posAtCoords({ left: event.clientX, top: event.clientY });
431
+ if (pos) {
432
+ editor.commands.setTextSelection(pos.pos);
433
+ }
434
+ void this.uploadAndInsertImage(editor, file, options);
435
+ return true;
436
+ }
437
+ /**
438
+ * Handle image paste event.
439
+ */
440
+ handlePaste(editor, event, options) {
441
+ const clipboardFiles = event.clipboardData?.files;
442
+ if (!clipboardFiles || clipboardFiles.length === 0) {
443
+ return false;
444
+ }
445
+ const imageFile = Array.from(clipboardFiles).find(file => file.type.startsWith("image/"));
446
+ if (!imageFile) {
447
+ return false;
448
+ }
449
+ event.preventDefault();
450
+ void this.uploadAndInsertImage(editor, imageFile, options);
451
+ return true;
452
+ }
453
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
454
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageService }); }
455
+ }
456
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageService, decorators: [{
457
+ type: Injectable
458
+ }] });
459
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRlLWltYWdlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLXRpcHRhcC1lZGl0b3Ivc3JjL2xpYi9zZXJ2aWNlcy9hdGUtaW1hZ2Uuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRXJFLE9BQU8sRUFBRSxZQUFZLEVBQUUsY0FBYyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3BELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQzs7QUFVcEQsTUFBTSxPQUFPLGVBQWU7SUFENUI7UUFFRSw4QkFBOEI7UUFDOUIsa0JBQWEsR0FBRyxNQUFNLENBQXNCLElBQUksQ0FBQyxDQUFDO1FBQ2xELG9CQUFlLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsS0FBSyxJQUFJLENBQUMsQ0FBQztRQUVoRSxxQkFBcUI7UUFDckIsZUFBVSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUVuQixTQUFJLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3JCLE1BQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUUzQywyQkFBMkI7UUFDM0IsZ0JBQVcsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDNUIsbUJBQWMsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0Isa0JBQWEsR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFM0I7OztXQUdHO1FBQ0gsa0JBQWEsR0FBaUMsSUFBSSxDQUFDO1FBRTNDLGtCQUFhLEdBQWtCLElBQUksQ0FBQztLQXFoQjdDO0lBbmhCQyxnREFBZ0Q7SUFDaEQsV0FBVyxDQUFDLE1BQWM7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bmplY3RhYmxlLCBzaWduYWwsIGNvbXB1dGVkLCBpbmplY3QgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgRWRpdG9yIH0gZnJvbSBcIkB0aXB0YXAvY29yZVwiO1xuaW1wb3J0IHsgaXNPYnNlcnZhYmxlLCBmaXJzdFZhbHVlRnJvbSB9IGZyb20gXCJyeGpzXCI7XG5pbXBvcnQgeyBBdGVJMThuU2VydmljZSB9IGZyb20gXCIuL2F0ZS1pMThuLnNlcnZpY2VcIjtcbmltcG9ydCB7XG4gIEF0ZVJlc2l6ZU9wdGlvbnMsXG4gIEF0ZUltYWdlVXBsb2FkT3B0aW9ucyxcbiAgQXRlSW1hZ2VVcGxvYWRIYW5kbGVyLFxuICBBdGVJbWFnZVVwbG9hZFJlc3VsdCxcbiAgQXRlSW1hZ2VEYXRhLFxufSBmcm9tIFwiLi4vbW9kZWxzL2F0ZS1pbWFnZS5tb2RlbFwiO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQXRlSW1hZ2VTZXJ2aWNlIHtcbiAgLyoqIFNpZ25hbHMgZm9yIGltYWdlIHN0YXRlICovXG4gIHNlbGVjdGVkSW1hZ2UgPSBzaWduYWw8QXRlSW1hZ2VEYXRhIHwgbnVsbD4obnVsbCk7XG4gIGlzSW1hZ2VTZWxlY3RlZCA9IGNvbXB1dGVkKCgpID0+IHRoaXMuc2VsZWN0ZWRJbWFnZSgpICE9PSBudWxsKTtcblxuICAvKiogUmVzaXppbmcgc3RhdGUgKi9cbiAgaXNSZXNpemluZyA9IHNpZ25hbChmYWxzZSk7XG5cbiAgcHJpdmF0ZSBpMThuID0gaW5qZWN0KEF0ZUkxOG5TZXJ2aWNlKTtcbiAgcHJpdmF0ZSByZWFkb25seSB0ID0gdGhpcy5pMThuLmltYWdlVXBsb2FkO1xuXG4gIC8qKiBVcGxvYWQgc3RhdGUgc2lnbmFscyAqL1xuICBpc1VwbG9hZGluZyA9IHNpZ25hbChmYWxzZSk7XG4gIHVwbG9hZFByb2dyZXNzID0gc2lnbmFsKDApO1xuICB1cGxvYWRNZXNzYWdlID0gc2lnbmFsKFwiXCIpO1xuXG4gIC8qKlxuICAgKiBDdXN0b20gdXBsb2FkIGhhbmRsZXIuXG4gICAqIElmIHNldCwgdGhpcyBoYW5kbGVyIHJlcGxhY2VzIHRoZSBkZWZhdWx0IGJhc2U2NCBjb252ZXJzaW9uLlxuICAgKi9cbiAgdXBsb2FkSGFuZGxlcjogQXRlSW1hZ2VVcGxvYWRIYW5kbGVyIHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSBjdXJyZW50RWRpdG9yOiBFZGl0b3IgfCBudWxsID0gbnVsbDtcblxuICAvKiogU2VsZWN0IGFuZCB0cmFjayBhbiBpbWFnZSBmcm9tIHRoZSBlZGl0b3IgKi9cbiAgc2VsZWN0SW1hZ2UoZWRpdG9yOiBFZGl0b3IpOiB2b2lkIHtcbiAgICBpZiAoZWRpdG9yLmlzQWN0aXZlKFwicmVzaXphYmxlSW1hZ2VcIikpIHtcbiAgICAgIGNvbnN0IGF0dHJzID0gZWRpdG9yLmdldEF0dHJpYnV0ZXMoXCJyZXNpemFibGVJbWFnZVwiKTtcbiAgICAgIHRoaXMuc2VsZWN0ZWRJbWFnZS5zZXQoe1xuICAgICAgICBzcmM6IGF0dHJzW1wic3JjXCJdLFxuICAgICAgICBhbHQ6IGF0dHJzW1wiYWx0XCJdLFxuICAgICAgICB0aXRsZTogYXR0cnNbXCJ0aXRsZVwiXSxcbiAgICAgICAgd2lkdGg6IGF0dHJzW1wid2lkdGhcIl0sXG4gICAgICAgIGhlaWdodDogYXR0cnNbXCJoZWlnaHRcIl0sXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zZWxlY3RlZEltYWdlLnNldChudWxsKTtcbiAgICB9XG4gIH1cblxuICBjbGVhclNlbGVjdGlvbigpOiB2b2lkIHtcbiAgICB0aGlzLnNlbGVjdGVkSW1hZ2Uuc2V0KG51bGwpO1xuICB9XG5cbiAgLyoqIEluc2VydCBhIG5ldyBpbWFnZSBhbmQgZW5zdXJlIGl0J3Mgc2VsZWN0ZWQgKi9cbiAgaW5zZXJ0SW1hZ2UoZWRpdG9yOiBFZGl0b3IsIGltYWdlRGF0YTogQXRlSW1hZ2VEYXRhKTogdm9pZCB7XG4gICAgZWRpdG9yXG4gICAgICAuY2hhaW4oKVxuICAgICAgLmZvY3VzKClcbiAgICAgIC5zZXRSZXNpemFibGVJbWFnZShpbWFnZURhdGEpXG4gICAgICAuY29tbWFuZCgoeyB0ciwgY29tbWFuZHMgfSkgPT4ge1xuICAgICAgICAvLyBTZWxlY3Rpb24gaXMgdXN1YWxseSBhZnRlciB0aGUgbm9kZS4gTm9kZSBpcyBhdCB0ci5zZWxlY3Rpb24uZnJvbSAtIDEuXG4gICAgICAgIGNvbnN0IHsgZnJvbSB9ID0gdHIuc2VsZWN0aW9uO1xuICAgICAgICAvLyBUcnkgdG8gc2VsZWN0IG5vZGUgYXQgY3VycmVudCBwb3MgKGlmIGl0IHdhcyBhbHJlYWR5IHNlbGVjdGVkKSBvciBwcmV2aW91cyBwb3NcbiAgICAgICAgcmV0dXJuIGNvbW1hbmRzLnNldE5vZGVTZWxlY3Rpb24oZnJvbSkgfHwgY29tbWFuZHMuc2V0Tm9kZVNlbGVjdGlvbihmcm9tIC0gMSkgfHwgdHJ1ZTtcbiAgICAgIH0pXG4gICAgICAucnVuKCk7XG4gIH1cblxuICAvKiogVXBkYXRlIGF0dHJpYnV0ZXMgb2YgdGhlIGN1cnJlbnRseSBhY3RpdmUgaW1hZ2UgKi9cbiAgdXBkYXRlSW1hZ2VBdHRyaWJ1dGVzKGVkaXRvcjogRWRpdG9yLCBhdHRyaWJ1dGVzOiBQYXJ0aWFsPEF0ZUltYWdlRGF0YT4pOiB2b2lkIHtcbiAgICBpZiAoZWRpdG9yLmlzQWN0aXZlKFwicmVzaXphYmxlSW1hZ2VcIikpIHtcbiAgICAgIGNvbnN0IHBvcyA9IGVkaXRvci5zdGF0ZS5zZWxlY3Rpb24uZnJvbTtcbiAgICAgIGVkaXRvclxuICAgICAgICAuY2hhaW4oKVxuICAgICAgICAuZm9jdXMoKVxuICAgICAgICAudXBkYXRlQXR0cmlidXRlcyhcInJlc2l6YWJsZUltYWdlXCIsIGF0dHJpYnV0ZXMpXG4gICAgICAgIC5zZXROb2RlU2VsZWN0aW9uKHBvcylcbiAgICAgICAgLnJ1bigpO1xuICAgICAgdGhpcy51cGRhdGVTZWxlY3RlZEltYWdlKGF0dHJpYnV0ZXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBSZXNpemUgaW1hZ2Ugd2l0aCBvcHRpb25hbCBhc3BlY3QgcmF0aW8gbWFpbnRlbmFuY2UgKi9cbiAgcmVzaXplSW1hZ2UoZWRpdG9yOiBFZGl0b3IsIG9wdGlvbnM6IEF0ZVJlc2l6ZU9wdGlvbnMpOiB2b2lkIHtcbiAgICBpZiAoIWVkaXRvci5pc0FjdGl2ZShcInJlc2l6YWJsZUltYWdlXCIpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgY3VycmVudEF0dHJzID0gZWRpdG9yLmdldEF0dHJpYnV0ZXMoXCJyZXNpemFibGVJbWFnZVwiKTtcbiAgICBsZXQgbmV3V2lkdGggPSBvcHRpb25zLndpZHRoO1xuICAgIGxldCBuZXdIZWlnaHQgPSBvcHRpb25zLmhlaWdodDtcblxuICAgIC8vIE1haW50YWluIGFzcGVjdCByYXRpbyBpZiByZXF1ZXN0ZWRcbiAgICBpZiAob3B0aW9ucy5tYWludGFpbkFzcGVjdFJhdGlvICE9PSBmYWxzZSAmJiBjdXJyZW50QXR0cnNbXCJ3aWR0aFwiXSAmJiBjdXJyZW50QXR0cnNbXCJoZWlnaHRcIl0pIHtcbiAgICAgIGNvbnN0IGFzcGVjdFJhdGlvID0gY3VycmVudEF0dHJzW1wid2lkdGhcIl0gLyBjdXJyZW50QXR0cnNbXCJoZWlnaHRcIl07XG5cbiAgICAgIGlmIChuZXdXaWR0aCAmJiAhbmV3SGVpZ2h0KSB7XG4gICAgICAgIG5ld0hlaWdodCA9IE1hdGgucm91bmQobmV3V2lkdGggLyBhc3BlY3RSYXRpbyk7XG4gICAgICB9IGVsc2UgaWYgKG5ld0hlaWdodCAmJiAhbmV3V2lkdGgpIHtcbiAgICAgICAgbmV3V2lkdGggPSBNYXRoLnJvdW5kKG5ld0hlaWdodCAqIGFzcGVjdFJhdGlvKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBcHBseSBtaW5pbXVtIGxpbWl0c1xuICAgIGlmIChuZXdXaWR0aCkge1xuICAgICAgbmV3V2lkdGggPSBNYXRoLm1heCg1MCwgbmV3V2lkdGgpO1xuICAgIH1cbiAgICBpZiAobmV3SGVpZ2h0KSB7XG4gICAgICBuZXdIZWlnaHQgPSBNYXRoLm1heCg1MCwgbmV3SGVpZ2h0KTtcbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZUltYWdlQXR0cmlidXRlcyhlZGl0b3IsIHtcbiAgICAgIHdpZHRoOiBuZXdXaWR0aCxcbiAgICAgIGhlaWdodDogbmV3SGVpZ2h0LFxuICAgIH0pO1xuICB9XG5cbiAgLyoqIFByZWRldGVybWluZWQgcmVzaXplIGhlbHBlcnMgdXNlZCBieSBVSSAqL1xuICByZXNpemVJbWFnZVRvU21hbGwoZWRpdG9yOiBFZGl0b3IpOiB2b2lkIHtcbiAgICB0aGlzLnJlc2l6ZUltYWdlKGVkaXRvciwgeyB3aWR0aDogMzAwLCBoZWlnaHQ6IDIwMCwgbWFpbnRhaW5Bc3BlY3RSYXRpbzogdHJ1ZSB9KTtcbiAgfVxuXG4gIHJlc2l6ZUltYWdlVG9NZWRpdW0oZWRpdG9yOiBFZGl0b3IpOiB2b2lkIHtcbiAgICB0aGlzLnJlc2l6ZUltYWdlKGVkaXRvciwgeyB3aWR0aDogNTAwLCBoZWlnaHQ6IDM1MCwgbWFpbnRhaW5Bc3BlY3RSYXRpbzogdHJ1ZSB9KTtcbiAgfVxuXG4gIHJlc2l6ZUltYWdlVG9MYXJnZShlZGl0b3I6IEVkaXRvcik6IHZvaWQge1xuICAgIHRoaXMucmVzaXplSW1hZ2UoZWRpdG9yLCB7IHdpZHRoOiA4MDAsIGhlaWdodDogNjAwLCBtYWludGFpbkFzcGVjdFJhdGlvOiB0cnVlIH0pO1xuICB9XG5cbiAgcmVzaXplSW1hZ2VUb09yaWdpbmFsKGVkaXRvcjogRWRpdG9yKTogdm9pZCB7XG4gICAgaWYgKCFlZGl0b3IuaXNBY3RpdmUoXCJyZXNpemFibGVJbWFnZVwiKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICBpbWcub25sb2FkID0gKCkgPT4ge1xuICAgICAgdGhpcy5yZXNpemVJbWFnZShlZGl0b3IsIHsgd2lkdGg6IGltZy5uYXR1cmFsV2lkdGgsIGhlaWdodDogaW1nLm5hdHVyYWxIZWlnaHQgfSk7XG4gICAgfTtcbiAgICBpbWcuc3JjID0gZWRpdG9yLmdldEF0dHJpYnV0ZXMoXCJyZXNpemFibGVJbWFnZVwiKVtcInNyY1wiXTtcbiAgfVxuXG4gIC8qKiBHZXQgY3VycmVudCBpbWFnZSBkaW1lbnNpb25zICovXG4gIGdldEltYWdlRGltZW5zaW9ucyhlZGl0b3I6IEVkaXRvcik6IHsgd2lkdGg6IG51bWJlcjsgaGVpZ2h0OiBudW1iZXIgfSB8IG51bGwge1xuICAgIGlmICghZWRpdG9yLmlzQWN0aXZlKFwicmVzaXphYmxlSW1hZ2VcIikpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCBhdHRycyA9IGVkaXRvci5nZXRBdHRyaWJ1dGVzKFwicmVzaXphYmxlSW1hZ2VcIik7XG4gICAgcmV0dXJuIHtcbiAgICAgIHdpZHRoOiBhdHRyc1tcIndpZHRoXCJdIHx8IDAsXG4gICAgICBoZWlnaHQ6IGF0dHJzW1wiaGVpZ2h0XCJdIHx8IDAsXG4gICAgfTtcbiAgfVxuXG4gIC8qKiBSZW1vdmUgdGhlIHNlbGVjdGVkIGltYWdlICovXG4gIGRlbGV0ZUltYWdlKGVkaXRvcjogRWRpdG9yKTogdm9pZCB7XG4gICAgaWYgKGVkaXRvci5pc0FjdGl2ZShcInJlc2l6YWJsZUltYWdlXCIpKSB7XG4gICAgICBlZGl0b3IuY2hhaW4oKS5mb2N1cygpLmRlbGV0ZVNlbGVjdGlvbigpLnJ1bigpO1xuICAgICAgdGhpcy5jbGVhclNlbGVjdGlvbigpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBEb3dubG9hZCB0aGUgY3VycmVudCBpbWFnZSAqL1xuICBkb3dubG9hZEltYWdlKGVkaXRvcjogRWRpdG9yKTogdm9pZCB7XG4gICAgY29uc3QgYXR0cnMgPSBlZGl0b3IuZ2V0QXR0cmlidXRlcyhcInJlc2l6YWJsZUltYWdlXCIpO1xuICAgIGlmICghYXR0cnMgfHwgIWF0dHJzW1wic3JjXCJdKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc3JjID0gYXR0cnNbXCJzcmNcIl07XG4gICAgY29uc3QgZmlsZU5hbWUgPSBhdHRyc1tcImFsdFwiXSB8fCBcImltYWdlXCI7XG5cbiAgICAvLyBEZXRlY3QgaWYgaXQncyBiYXNlNjQgb3IgcmVtb3RlIFVSTFxuICAgIGlmIChcbiAgICAgIHNyYy5zdGFydHNXaXRoKFwiZGF0YTpcIikgfHxcbiAgICAgIHNyYy5zdGFydHNXaXRoKFwiYmxvYjpcIikgfHxcbiAgICAgIHNyYy5zdGFydHNXaXRoKHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4pXG4gICAgKSB7XG4gICAgICBjb25zdCBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImFcIik7XG4gICAgICBsaW5rLmhyZWYgPSBzcmM7XG4gICAgICBsaW5rLmRvd25sb2FkID0gZmlsZU5hbWU7XG4gICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGxpbmspO1xuICAgICAgbGluay5jbGljaygpO1xuICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChsaW5rKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRm9yIHJlbW90ZSBVUkxzLCB3ZSB0cnkgdG8gZmV0Y2ggaXQgdG8gYnlwYXNzIGNyb3NzLW9yaWdpbiByZXN0cmljdGlvbnMgb24gJ2Rvd25sb2FkJyBhdHRyaWJ1dGVcbiAgICAgIGZldGNoKHNyYylcbiAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4gcmVzcG9uc2UuYmxvYigpKVxuICAgICAgICAudGhlbihibG9iID0+IHtcbiAgICAgICAgICBjb25zdCB1cmwgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKTtcbiAgICAgICAgICBjb25zdCBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImFcIik7XG4gICAgICAgICAgbGluay5ocmVmID0gdXJsO1xuICAgICAgICAgIGxpbmsuZG93bmxvYWQgPSBmaWxlTmFtZTtcbiAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGxpbmspO1xuICAgICAgICAgIGxpbmsuY2xpY2soKTtcbiAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGxpbmspO1xuICAgICAgICAgIHdpbmRvdy5VUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnIgPT4ge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBkb3dubG9hZGluZyBpbWFnZTpcIiwgZXJyKTtcbiAgICAgICAgICAvLyBGYWxsYmFjayB0byBvcGVuaW5nIGluIG5ldyB0YWJcbiAgICAgICAgICB3aW5kb3cub3BlbihzcmMsIFwiX2JsYW5rXCIpO1xuICAgICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVNlbGVjdGVkSW1hZ2UoYXR0cmlidXRlczogUGFydGlhbDxBdGVJbWFnZURhdGE+KTogdm9pZCB7XG4gICAgY29uc3QgY3VycmVudCA9IHRoaXMuc2VsZWN0ZWRJbWFnZSgpO1xuICAgIGlmIChjdXJyZW50KSB7XG4gICAgICB0aGlzLnNlbGVjdGVkSW1hZ2Uuc2V0KHsgLi4uY3VycmVudCwgLi4uYXR0cmlidXRlcyB9KTtcbiAgICB9XG4gIH1cblxuICAvKiogVmFsaWRhdGUgZmlsZSB0eXBlIGFuZCBzaXplICovXG4gIHZhbGlkYXRlSW1hZ2UoXG4gICAgZmlsZTogRmlsZSxcbiAgICBvcHRpb25zPzogeyBtYXhTaXplPzogbnVtYmVyOyBhbGxvd2VkVHlwZXM/OiBzdHJpbmdbXSB9XG4gICk6IHsgdmFsaWQ6IGJvb2xlYW47IGVycm9yPzogc3RyaW5nIH0ge1xuICAgIGNvbnN0IG1heFNpemUgPSBvcHRpb25zPy5tYXhTaXplIHx8IDEwICogMTAyNCAqIDEwMjQ7XG4gICAgY29uc3QgYWxsb3dlZFR5cGVzID0gb3B0aW9ucz8uYWxsb3dlZFR5cGVzIHx8IFtdO1xuXG4gICAgaWYgKGFsbG93ZWRUeXBlcy5sZW5ndGggPiAwICYmICFhbGxvd2VkVHlwZXMuaW5jbHVkZXMoZmlsZS50eXBlKSkge1xuICAgICAgcmV0dXJuIHsgdmFsaWQ6IGZhbHNlLCBlcnJvcjogdGhpcy50KCkuaW52YWxpZEZpbGVUeXBlIH07XG4gICAgfVxuXG4gICAgaWYgKGZpbGUuc2l6ZSA+IG1heFNpemUpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHZhbGlkOiBmYWxzZSxcbiAgICAgICAgZXJyb3I6IGAke3RoaXMudCgpLmltYWdlVG9vTGFyZ2V9IChtYXggJHtNYXRoLnJvdW5kKG1heFNpemUgLyAxMDI0IC8gMTAyNCl9TUIpYCxcbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiB7IHZhbGlkOiB0cnVlIH07XG4gIH1cblxuICAvKiogQ29tcHJlc3MgYW5kIHByb2Nlc3MgaW1hZ2Ugb24gY2xpZW50IHNpZGUgKi9cbiAgYXN5bmMgY29tcHJlc3NJbWFnZShcbiAgICBmaWxlOiBGaWxlLFxuICAgIHF1YWxpdHkgPSAwLjgsXG4gICAgbWF4V2lkdGggPSAxOTIwLFxuICAgIG1heEhlaWdodCA9IDEyMDBcbiAgKTogUHJvbWlzZTxBdGVJbWFnZVVwbG9hZFJlc3VsdD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiY2FudmFzXCIpO1xuICAgICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcbiAgICAgIGNvbnN0IGltZyA9IG5ldyBJbWFnZSgpO1xuXG4gICAgICBpbWcub25sb2FkID0gKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5pc1VwbG9hZGluZygpKSB7XG4gICAgICAgICAgdGhpcy51cGxvYWRQcm9ncmVzcy5zZXQoNDApO1xuICAgICAgICAgIHRoaXMudXBsb2FkTWVzc2FnZS5zZXQodGhpcy50KCkucmVzaXppbmcpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHsgd2lkdGgsIGhlaWdodCB9ID0gaW1nO1xuICAgICAgICBpZiAod2lkdGggPiBtYXhXaWR0aCB8fCBoZWlnaHQgPiBtYXhIZWlnaHQpIHtcbiAgICAgICAgICBjb25zdCByYXRpbyA9IE1hdGgubWluKG1heFdpZHRoIC8gd2lkdGgsIG1heEhlaWdodCAvIGhlaWdodCk7XG4gICAgICAgICAgd2lkdGggKj0gcmF0aW87XG4gICAgICAgICAgaGVpZ2h0ICo9IHJhdGlvO1xuICAgICAgICB9XG5cbiAgICAgICAgY2FudmFzLndpZHRoID0gd2lkdGg7XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgIGN0eD8uZHJhd0ltYWdlKGltZywgMCwgMCwgd2lkdGgsIGhlaWdodCk7XG5cbiAgICAgICAgaWYgKHRoaXMuaXNVcGxvYWRpbmcoKSkge1xuICAgICAgICAgIHRoaXMudXBsb2FkUHJvZ3Jlc3Muc2V0KDYwKTtcbiAgICAgICAgICB0aGlzLnVwbG9hZE1lc3NhZ2Uuc2V0KHRoaXMudCgpLmNvbXByZXNzaW5nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNhbnZhcy50b0Jsb2IoXG4gICAgICAgICAgYmxvYiA9PiB7XG4gICAgICAgICAgICBpZiAoYmxvYikge1xuICAgICAgICAgICAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgICAgICAgICAgICByZWFkZXIub25sb2FkID0gZSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgYmFzZTY0ID0gZS50YXJnZXQ/LnJlc3VsdCBhcyBzdHJpbmc7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSh7XG4gICAgICAgICAgICAgICAgICBzcmM6IGJhc2U2NCxcbiAgICAgICAgICAgICAgICAgIG5hbWU6IGZpbGUubmFtZSxcbiAgICAgICAgICAgICAgICAgIHNpemU6IGJsb2Iuc2l6ZSxcbiAgICAgICAgICAgICAgICAgIHR5cGU6IGZpbGUudHlwZSxcbiAgICAgICAgICAgICAgICAgIHdpZHRoOiBNYXRoLnJvdW5kKHdpZHRoKSxcbiAgICAgICAgICAgICAgICAgIGhlaWdodDogTWF0aC5yb3VuZChoZWlnaHQpLFxuICAgICAgICAgICAgICAgICAgb3JpZ2luYWxTaXplOiBmaWxlLnNpemUsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGJsb2IpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcih0aGlzLnQoKS5jb21wcmVzc2lvbkVycm9yKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBmaWxlLnR5cGUsXG4gICAgICAgICAgcXVhbGl0eVxuICAgICAgICApO1xuICAgICAgfTtcblxuICAgICAgaW1nLm9uZXJyb3IgPSAoKSA9PiByZWplY3QobmV3IEVycm9yKHRoaXMudCgpLmxvYWRFcnJvcikpO1xuICAgICAgaW1nLnNyYyA9IFVSTC5jcmVhdGVPYmplY3RVUkwoZmlsZSk7XG4gICAgfSk7XG4gIH1cblxuICAvKiogQ29yZSB1cGxvYWQgbG9naWMgd2l0aCBwcm9ncmVzcyB0cmFja2luZyAqL1xuICBwcml2YXRlIGFzeW5jIHVwbG9hZEltYWdlV2l0aFByb2dyZXNzKFxuICAgIGVkaXRvcjogRWRpdG9yLFxuICAgIGZpbGU6IEZpbGUsXG4gICAgaW5zZXJ0aW9uU3RyYXRlZ3k6IChlZGl0b3I6IEVkaXRvciwgcmVzdWx0OiBBdGVJbWFnZVVwbG9hZFJlc3VsdCkgPT4gdm9pZCxcbiAgICBhY3Rpb25NZXNzYWdlOiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IEF0ZUltYWdlVXBsb2FkT3B0aW9uc1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5jdXJyZW50RWRpdG9yID0gZWRpdG9yO1xuICAgICAgdGhpcy5pc1VwbG9hZGluZy5zZXQodHJ1ZSk7XG4gICAgICB0aGlzLnVwbG9hZFByb2dyZXNzLnNldCgxMCk7XG4gICAgICB0aGlzLnVwbG9hZE1lc3NhZ2Uuc2V0KHRoaXMudCgpLnZhbGlkYXRpbmcpO1xuICAgICAgdGhpcy5mb3JjZUVkaXRvclVwZGF0ZSgpO1xuXG4gICAgICBjb25zdCB2YWxpZGF0aW9uID0gdGhpcy52YWxpZGF0ZUltYWdlKGZpbGUsIHtcbiAgICAgICAgbWF4U2l6ZTogb3B0aW9ucz8ubWF4U2l6ZSxcbiAgICAgICAgYWxsb3dlZFR5cGVzOiBvcHRpb25zPy5hbGxvd2VkVHlwZXMsXG4gICAgICB9KTtcbiAgICAgIGlmICghdmFsaWRhdGlvbi52YWxpZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IodmFsaWRhdGlvbi5lcnJvcik7XG4gICAgICB9XG5cbiAgICAgIHRoaXMudXBsb2FkUHJvZ3Jlc3Muc2V0KDMwKTtcbiAgICAgIHRoaXMudXBsb2FkTWVzc2FnZS5zZXQodGhpcy50KCkuY29tcHJlc3NpbmcpO1xuICAgICAgdGhpcy5mb3JjZUVkaXRvclVwZGF0ZSgpO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmNvbXByZXNzSW1hZ2UoXG4gICAgICAgIGZpbGUsXG4gICAgICAgIG9wdGlvbnM/LnF1YWxpdHkgfHwgMC44LFxuICAgICAgICBvcHRpb25zPy5tYXhXaWR0aCB8fCAxOTIwLFxuICAgICAgICBvcHRpb25zPy5tYXhIZWlnaHQgfHwgMTIwMFxuICAgICAgKTtcblxuICAgICAgdGhpcy51cGxvYWRQcm9ncmVzcy5zZXQoNzApO1xuXG4gICAgICAvLyBIYW5kbGUgY3VzdG9tIHVwbG9hZCBpZiBoYW5kbGVyIGlzIHByb3ZpZGVkXG4gICAgICBpZiAodGhpcy51cGxvYWRIYW5kbGVyKSB7XG4gICAgICAgIHRoaXMudXBsb2FkTWVzc2FnZS5zZXQodGhpcy50KCkudXBsb2FkaW5nVG9TZXJ2ZXIpO1xuICAgICAgICB0aGlzLmZvcmNlRWRpdG9yVXBkYXRlKCk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBoYW5kbGVyUmVzcG9uc2UgPSB0aGlzLnVwbG9hZEhhbmRsZXIoe1xuICAgICAgICAgICAgZmlsZSxcbiAgICAgICAgICAgIHdpZHRoOiByZXN1bHQud2lkdGggfHwgMCxcbiAgICAgICAgICAgIGhlaWdodDogcmVzdWx0LmhlaWdodCB8fCAwLFxuICAgICAgICAgICAgdHlwZTogcmVzdWx0LnR5cGUsXG4gICAgICAgICAgICBiYXNlNjQ6IHJlc3VsdC5zcmMsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjb25zdCBoYW5kbGVyUmVzdWx0ID0gaXNPYnNlcnZhYmxlKGhhbmRsZXJSZXNwb25zZSlcbiAgICAgICAgICAgID8gYXdhaXQgZmlyc3RWYWx1ZUZyb20oaGFuZGxlclJlc3BvbnNlKVxuICAgICAgICAgICAgOiBhd2FpdCBoYW5kbGVyUmVzcG9uc2U7XG5cbiAgICAgICAgICByZXN1bHQuc3JjID0gaGFuZGxlclJlc3VsdC5zcmM7XG4gICAgICAgICAgaWYgKGhhbmRsZXJSZXN1bHQuYWx0KSB7XG4gICAgICAgICAgICByZXN1bHQubmFtZSA9IGhhbmRsZXJSZXN1bHQuYWx0O1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoaGFuZGxlckVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcih0aGlzLnQoKS51cGxvYWRFcnJvciwgaGFuZGxlckVycm9yKTtcbiAgICAgICAgICB0aHJvdyBoYW5kbGVyRXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy51cGxvYWRQcm9ncmVzcy5zZXQoOTApO1xuICAgICAgdGhpcy51cGxvYWRNZXNzYWdlLnNldChhY3Rpb25NZXNzYWdlKTtcbiAgICAgIHRoaXMuZm9yY2VFZGl0b3JVcGRhdGUoKTtcblxuICAgICAgLy8gRmluYWwgaW5zZXJ0aW9uXG4gICAgICBpbnNlcnRpb25TdHJhdGVneShlZGl0b3IsIHJlc3VsdCk7XG5cbiAgICAgIHRoaXMucmVzZXRVcGxvYWRTdGF0ZSgpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLnJlc2V0VXBsb2FkU3RhdGUoKTtcbiAgICAgIGNvbnNvbGUuZXJyb3IodGhpcy50KCkudXBsb2FkRXJyb3IsIGVycm9yKTtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVzZXRVcGxvYWRTdGF0ZSgpIHtcbiAgICB0aGlzLmlzVXBsb2FkaW5nLnNldChmYWxzZSk7XG4gICAgdGhpcy51cGxvYWRQcm9ncmVzcy5zZXQoMCk7XG4gICAgdGhpcy51cGxvYWRNZXNzYWdlLnNldChcIlwiKTtcbiAgICB0aGlzLmZvcmNlRWRpdG9yVXBkYXRlKCk7XG4gICAgdGhpcy5jdXJyZW50RWRpdG9yID0gbnVsbDtcbiAgfVxuXG4gIC8qKiBNYWluIGVudHJ5IHBvaW50IGZvciBmaWxlIHVwbG9hZCBhbmQgaW5zZXJ0aW9uICovXG4gIGFzeW5jIHVwbG9hZEFuZEluc2VydEltYWdlKFxuICAgIGVkaXRvcjogRWRpdG9yLFxuICAgIGZpbGU6IEZpbGUsXG4gICAgb3B0aW9ucz86IEF0ZUltYWdlVXBsb2FkT3B0aW9uc1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy51cGxvYWRJbWFnZVdpdGhQcm9ncmVzcyhcbiAgICAgIGVkaXRvcixcbiAgICAgIGZpbGUsXG4gICAgICAoZWQsIHJlc3VsdCkgPT4ge1xuICAgICAgICB0aGlzLmluc2VydEltYWdlKGVkLCB7XG4gICAgICAgICAgc3JjOiByZXN1bHQuc3JjLFxuICAgICAgICAgIGFsdDogcmVzdWx0Lm5hbWUsXG4gICAgICAgICAgdGl0bGU6IGAke3Jlc3VsdC5uYW1lfSAoJHtyZXN1bHQud2lkdGh9w5cke3Jlc3VsdC5oZWlnaHR9KWAsXG4gICAgICAgICAgd2lkdGg6IHJlc3VsdC53aWR0aCxcbiAgICAgICAgICBoZWlnaHQ6IHJlc3VsdC5oZWlnaHQsXG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICAgIHRoaXMudCgpLmluc2VydGluZ0ltYWdlLFxuICAgICAgb3B0aW9uc1xuICAgICk7XG4gIH1cblxuICAvKiogVHJpZ2dlciBhbiBlZGl0b3IgdHJhbnNhY3Rpb24gdG8gZm9yY2UgZGVjb3JhdGlvbiB1cGRhdGUgKi9cbiAgcHJpdmF0ZSBmb3JjZUVkaXRvclVwZGF0ZSgpIHtcbiAgICBpZiAodGhpcy5jdXJyZW50RWRpdG9yKSB7XG4gICAgICBjb25zdCB7IHRyIH0gPSB0aGlzLmN1cnJlbnRFZGl0b3Iuc3RhdGU7XG4gICAgICB0aGlzLmN1cnJlbnRFZGl0b3Iudmlldy5kaXNwYXRjaCh0cik7XG4gICAgfVxuICB9XG5cbiAgLyoqIEdlbmVyaWMgaGVscGVyIHRvIG9wZW4gZmlsZSBwaWNrZXIgYW5kIHByb2Nlc3Mgc2VsZWN0aW9uICovXG4gIHByaXZhdGUgYXN5bmMgc2VsZWN0RmlsZUFuZFByb2Nlc3MoXG4gICAgZWRpdG9yOiBFZGl0b3IsXG4gICAgdXBsb2FkTWV0aG9kOiAoZWRpdG9yOiBFZGl0b3IsIGZpbGU6IEZpbGUsIG9wdGlvbnM/OiBBdGVJbWFnZVVwbG9hZE9wdGlvbnMpID0+IFByb21pc2U8dm9pZD4sXG4gICAgb3B0aW9ucz86IEF0ZUltYWdlVXBsb2FkT3B0aW9uc1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgaW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiaW5wdXRcIik7XG4gICAgICBpbnB1dC50eXBlID0gXCJmaWxlXCI7XG5cbiAgICAgIC8vIFVzZSBhbGxvd2VkVHlwZXMgaWYgcHJvdmlkZWQsIG90aGVyd2lzZSBkZWZhdWx0IHRvIGltYWdlLypcbiAgICAgIGlmIChvcHRpb25zPy5hbGxvd2VkVHlwZXMgJiYgb3B0aW9ucy5hbGxvd2VkVHlwZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBpbnB1dC5hY2NlcHQgPSBvcHRpb25zLmFsbG93ZWRUeXBlcy5qb2luKFwiLFwiKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlucHV0LmFjY2VwdCA9IFwiaW1hZ2UvKlwiO1xuICAgICAgfVxuXG4gICAgICBpbnB1dC5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG5cbiAgICAgIGlucHV0LmFkZEV2ZW50TGlzdGVuZXIoXCJjaGFuZ2VcIiwgYXN5bmMgZSA9PiB7XG4gICAgICAgIGNvbnN0IGZpbGUgPSAoZS50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkuZmlsZXM/LlswXTtcbiAgICAgICAgaWYgKGZpbGUgJiYgZmlsZS50eXBlLnN0YXJ0c1dpdGgoXCJpbWFnZS9cIikpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdXBsb2FkTWV0aG9kKGVkaXRvciwgZmlsZSwgb3B0aW9ucyk7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IodGhpcy50KCkubm9GaWxlU2VsZWN0ZWQpKTtcbiAgICAgICAgfVxuICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGlucHV0KTtcbiAgICAgIH0pO1xuXG4gICAgICBpbnB1dC5hZGRFdmVudExpc3RlbmVyKFwiY2FuY2VsXCIsICgpID0+IHtcbiAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChpbnB1dCk7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IodGhpcy50KCkuc2VsZWN0aW9uQ2FuY2VsbGVkKSk7XG4gICAgICB9KTtcblxuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChpbnB1dCk7XG4gICAgICBpbnB1dC5jbGljaygpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqIFNlbGVjdCBmaWxlIGFuZCB1cGxvYWQgYXMgbmV3IGltYWdlICovXG4gIGFzeW5jIHNlbGVjdEFuZFVwbG9hZEltYWdlKGVkaXRvcjogRWRpdG9yLCBvcHRpb25zPzogQXRlSW1hZ2VVcGxvYWRPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0RmlsZUFuZFByb2Nlc3MoZWRpdG9yLCB0aGlzLnVwbG9hZEFuZEluc2VydEltYWdlLmJpbmQodGhpcyksIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqIFNlbGVjdCBmaWxlIGFuZCByZXBsYWNlIGN1cnJlbnRseSBzZWxlY3RlZCBpbWFnZSAqL1xuICBhc3luYyBzZWxlY3RBbmRSZXBsYWNlSW1hZ2UoZWRpdG9yOiBFZGl0b3IsIG9wdGlvbnM/OiBBdGVJbWFnZVVwbG9hZE9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBObyBuZWVkIGZvciBjb21wbGljYXRlZCBiYWNrdXAvcmVzdG9yZSBub3cgdGhhdCB3ZSBkb24ndCBkZWxldGUgcHJlbWF0dXJlbHkuXG4gICAgLy8gVGhlIHVwbG9hZEFuZFJlcGxhY2VJbWFnZSB3aWxsIGhhbmRsZSB0aGUgYXRvbWljIHJlcGxhY2VtZW50LlxuICAgIHJldHVybiB0aGlzLnNlbGVjdEZpbGVBbmRQcm9jZXNzKGVkaXRvciwgdGhpcy51cGxvYWRBbmRSZXBsYWNlSW1hZ2UuYmluZCh0aGlzKSwgb3B0aW9ucyk7XG4gIH1cblxuICAvKiogSW50ZXJuYWwgaGVscGVyIHVzZWQgYnkgcmVwbGFjZW1lbnQgbG9naWMgKi9cbiAgYXN5bmMgdXBsb2FkQW5kUmVwbGFjZUltYWdlKFxuICAgIGVkaXRvcjogRWRpdG9yLFxuICAgIGZpbGU6IEZpbGUsXG4gICAgb3B0aW9ucz86IEF0ZUltYWdlVXBsb2FkT3B0aW9uc1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBTdG9yZSBjdXJyZW50IHBvc2l0aW9uIHRvIGVuc3VyZSB3ZSBjYW4gcmUtc2VsZWN0IHRoZSBpbWFnZSBldmVuIGlmIHNlbGVjdGlvbiBibHVycyBkdXJpbmcgdXBsb2FkXG4gICAgY29uc3Qgd2FzQWN0aXZlID0gZWRpdG9yLmlzQWN0aXZlKFwicmVzaXphYmxlSW1hZ2VcIik7XG5cbiAgICBhd2FpdCB0aGlzLnVwbG9hZEltYWdlV2l0aFByb2dyZXNzKFxuICAgICAgZWRpdG9yLFxuICAgICAgZmlsZSxcbiAgICAgIChlZCwgcmVzdWx0KSA9PiB7XG4gICAgICAgIGNvbnN0IGltYWdlRGF0YSA9IHtcbiAgICAgICAgICBzcmM6IHJlc3VsdC5zcmMsXG4gICAgICAgICAgYWx0OiByZXN1bHQubmFtZSxcbiAgICAgICAgICB0aXRsZTogYCR7cmVzdWx0Lm5hbWV9ICgke3Jlc3VsdC53aWR0aH3DlyR7cmVzdWx0LmhlaWdodH0pYCxcbiAgICAgICAgICB3aWR0aDogcmVzdWx0LndpZHRoLFxuICAgICAgICAgIGhlaWdodDogcmVzdWx0LmhlaWdodCxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBJZiB0aGUgaW1hZ2Ugd2FzIGFjdGl2ZSBvciBpcyBzdGlsbCBhY3RpdmUsIHVwZGF0ZSBpdCBhdG9taWNhbGx5XG4gICAgICAgIGlmICh3YXNBY3RpdmUgfHwgZWQuaXNBY3RpdmUoXCJyZXNpemFibGVJbWFnZVwiKSkge1xuICAgICAgICAgIGVkLmNoYWluKClcbiAgICAgICAgICAgIC5mb2N1cygpXG4gICAgICAgICAgICAudXBkYXRlQXR0cmlidXRlcyhcInJlc2l6YWJsZUltYWdlXCIsIGltYWdlRGF0YSlcbiAgICAgICAgICAgIC5jb21tYW5kKCh7IHRyLCBjb21tYW5kcyB9KSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IHsgZnJvbSB9ID0gdHIuc2VsZWN0aW9uO1xuICAgICAgICAgICAgICAvLyBSZS1zZWxlY3QgdGhlIG5vZGUgYXQgaXRzIG1hcHBlZCBwb3NpdGlvbiBvciBjdXJyZW50IHNlbGVjdGlvblxuICAgICAgICAgICAgICByZXR1cm4gY29tbWFuZHMuc2V0Tm9kZVNlbGVjdGlvbihmcm9tKSB8fCBjb21tYW5kcy5zZXROb2RlU2VsZWN0aW9uKGZyb20gLSAxKSB8fCB0cnVlO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5ydW4oKTtcbiAgICAgICAgICB0aGlzLnVwZGF0ZVNlbGVjdGVkSW1hZ2UoaW1hZ2VEYXRhKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBPdGhlcndpc2UgcmVwbGFjZSB3aGF0ZXZlciBpcyBzZWxlY3RlZCAob3IgaW5zZXJ0IGF0IGN1cnNvcilcbiAgICAgICAgICB0aGlzLmluc2VydEltYWdlKGVkLCBpbWFnZURhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWZ0ZXIgcmVwbGFjZW1lbnQsIGVuc3VyZSB0aGUgaW1hZ2UgaXMgdHJhY2tlZCBpbiBvdXIgc2lnbmFsc1xuICAgICAgICB0aGlzLnNlbGVjdEltYWdlKGVkKTtcbiAgICAgIH0sXG4gICAgICB0aGlzLnQoKS5yZXBsYWNpbmdJbWFnZSxcbiAgICAgIG9wdGlvbnNcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSBpbWFnZSBkcm9wIGV2ZW50LlxuICAgKiBDYWxjdWxhdGVzIHRoZSBwb3NpdGlvbiBmcm9tIGNvb3JkaW5hdGVzIGFuZCBzZXRzIHRoZSBzZWxlY3Rpb24gYWNjb3JkaW5nbHkuXG4gICAqL1xuICBoYW5kbGVEcm9wKGVkaXRvcjogRWRpdG9yLCBldmVudDogRHJhZ0V2ZW50LCBvcHRpb25zPzogQXRlSW1hZ2VVcGxvYWRPcHRpb25zKTogYm9vbGVhbiB7XG4gICAgY29uc3QgZmlsZXMgPSBldmVudC5kYXRhVHJhbnNmZXI/LmZpbGVzO1xuICAgIGlmICghZmlsZXMgfHwgZmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgZmlsZSA9IEFycmF5LmZyb20oZmlsZXMpLmZpbmQoZiA9PiBmLnR5cGUuc3RhcnRzV2l0aChcImltYWdlL1wiKSk7XG4gICAgaWYgKCFmaWxlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIC8vIFRyeSB0byBmaW5kIHRoZSBkcm9wIHBvc2l0aW9uIGZyb20gY29vcmRpbmF0ZXNcbiAgICBjb25zdCBwb3MgPSBlZGl0b3Iudmlldy5wb3NBdENvb3Jkcyh7IGxlZnQ6IGV2ZW50LmNsaWVudFgsIHRvcDogZXZlbnQuY2xpZW50WSB9KTtcbiAgICBpZiAocG9zKSB7XG4gICAgICBlZGl0b3IuY29tbWFuZHMuc2V0VGV4dFNlbGVjdGlvbihwb3MucG9zKTtcbiAgICB9XG5cbiAgICB2b2lkIHRoaXMudXBsb2FkQW5kSW5zZXJ0SW1hZ2UoZWRpdG9yLCBmaWxlLCBvcHRpb25zKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgaW1hZ2UgcGFzdGUgZXZlbnQuXG4gICAqL1xuICBoYW5kbGVQYXN0ZShlZGl0b3I6IEVkaXRvciwgZXZlbnQ6IENsaXBib2FyZEV2ZW50LCBvcHRpb25zPzogQXRlSW1hZ2VVcGxvYWRPcHRpb25zKTogYm9vbGVhbiB7XG4gICAgY29uc3QgY2xpcGJvYXJkRmlsZXMgPSBldmVudC5jbGlwYm9hcmREYXRhPy5maWxlcztcbiAgICBpZiAoIWNsaXBib2FyZEZpbGVzIHx8IGNsaXBib2FyZEZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGltYWdlRmlsZSA9IEFycmF5LmZyb20oY2xpcGJvYXJkRmlsZXMpLmZpbmQoZmlsZSA9PiBmaWxlLnR5cGUuc3RhcnRzV2l0aChcImltYWdlL1wiKSk7XG4gICAgaWYgKCFpbWFnZUZpbGUpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHZvaWQgdGhpcy51cGxvYWRBbmRJbnNlcnRJbWFnZShlZGl0b3IsIGltYWdlRmlsZSwgb3B0aW9ucyk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,99 @@
1
+ import { Injectable, signal } from "@angular/core";
2
+ import * as i0 from "@angular/core";
3
+ export class AteLinkService {
4
+ constructor() {
5
+ // ============================================
6
+ // State Signals (owned by this service)
7
+ // ============================================
8
+ /** Whether link edit mode is active */
9
+ this.editMode = signal(false);
10
+ /** Reference to the element that triggered the menu (for anchoring) */
11
+ this.menuTrigger = signal(null);
12
+ /** Whether the user is currently interacting with the link UI (input focus) */
13
+ this.isInteracting = signal(false);
14
+ }
15
+ // ============================================
16
+ // Menu Lifecycle Methods
17
+ // ============================================
18
+ /**
19
+ * Open the link edit menu.
20
+ */
21
+ open(trigger) {
22
+ this.menuTrigger.set(trigger || null);
23
+ this.editMode.set(true);
24
+ }
25
+ /**
26
+ * Close the link edit menu.
27
+ */
28
+ close() {
29
+ this.editMode.set(false);
30
+ this.isInteracting.set(false);
31
+ }
32
+ /**
33
+ * Final cleanup (called after UI is hidden)
34
+ */
35
+ done() {
36
+ this.menuTrigger.set(null);
37
+ }
38
+ /**
39
+ * Set interaction state
40
+ */
41
+ setInteracting(value) {
42
+ this.isInteracting.set(value);
43
+ }
44
+ /**
45
+ * Toggle link mode from UI.
46
+ * If a URL string is provided, applies the link and closes.
47
+ * If an Event is provided, extracts the trigger for anchoring.
48
+ */
49
+ toggle(editor, urlOrEvent) {
50
+ if (!editor) {
51
+ return;
52
+ }
53
+ // If a string URL is provided, set the link and close
54
+ if (urlOrEvent && typeof urlOrEvent === "string") {
55
+ this.setLink(editor, urlOrEvent);
56
+ return;
57
+ }
58
+ // If an Event is provided, extract the trigger element
59
+ let trigger;
60
+ if (urlOrEvent && typeof urlOrEvent !== "string") {
61
+ const target = urlOrEvent.target;
62
+ trigger =
63
+ urlOrEvent.currentTarget ||
64
+ target?.closest("button") ||
65
+ target;
66
+ }
67
+ // Open the edit menu
68
+ this.open(trigger);
69
+ }
70
+ // ============================================
71
+ // Link Commands
72
+ // ============================================
73
+ /**
74
+ * Apply a link to the current selection.
75
+ */
76
+ setLink(editor, url) {
77
+ if (!editor) {
78
+ return;
79
+ }
80
+ editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
81
+ this.close();
82
+ }
83
+ /**
84
+ * Remove link from the current selection.
85
+ */
86
+ unsetLink(editor) {
87
+ if (!editor) {
88
+ return;
89
+ }
90
+ editor.chain().focus().extendMarkRange("link").unsetLink().run();
91
+ this.close();
92
+ }
93
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteLinkService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
94
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteLinkService }); }
95
+ }
96
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteLinkService, decorators: [{
97
+ type: Injectable
98
+ }] });
99
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRlLWxpbmsuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItdGlwdGFwLWVkaXRvci9zcmMvbGliL3NlcnZpY2VzL2F0ZS1saW5rLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7O0FBSW5ELE1BQU0sT0FBTyxjQUFjO0lBRDNCO1FBRUUsK0NBQStDO1FBQy9DLHdDQUF3QztRQUN4QywrQ0FBK0M7UUFFL0MsdUNBQXVDO1FBQzlCLGFBQVEsR0FBRyxNQUFNLENBQVUsS0FBSyxDQUFDLENBQUM7UUFFM0MsdUVBQXVFO1FBQzlELGdCQUFXLEdBQUcsTUFBTSxDQUFxQixJQUFJLENBQUMsQ0FBQztRQUV4RCwrRUFBK0U7UUFDdEUsa0JBQWEsR0FBRyxNQUFNLENBQVUsS0FBSyxDQUFDLENBQUM7S0EyRmpEO0lBekZDLCtDQUErQztJQUMvQyx5QkFBeUI7SUFDekIsK0NBQStDO0lBRS9DOztPQUVHO0lBQ0gsSUFBSSxDQUFDLE9BQXFCO1FBQ3hCLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsQ0FBQztRQUN0QyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLO1FBQ0gsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSTtRQUNGLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdCLENBQUM7SUFFRDs7T0FFRztJQUNILGNBQWMsQ0FBQyxLQUFjO1FBQzNCLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsTUFBTSxDQUFDLE1BQWMsRUFBRSxVQUEyQjtRQUNoRCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixPQUFPO1FBQ1QsQ0FBQztRQUVELHNEQUFzRDtRQUN0RCxJQUFJLFVBQVUsSUFBSSxPQUFPLFVBQVUsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUNqRCxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQztZQUNqQyxPQUFPO1FBQ1QsQ0FBQztRQUVELHVEQUF1RDtRQUN2RCxJQUFJLE9BQWdDLENBQUM7UUFDckMsSUFBSSxVQUFVLElBQUksT0FBTyxVQUFVLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDakQsTUFBTSxNQUFNLEdBQUksVUFBb0IsQ0FBQyxNQUFxQixDQUFDO1lBQzNELE9BQU87Z0JBQ0gsVUFBb0IsQ0FBQyxhQUE2QjtvQkFDbkQsTUFBa0IsRUFBRSxPQUFPLENBQUMsUUFBUSxDQUFDO29CQUN0QyxNQUFNLENBQUM7UUFDWCxDQUFDO1FBRUQscUJBQXFCO1FBQ3JCLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDckIsQ0FBQztJQUVELCtDQUErQztJQUMvQyxnQkFBZ0I7SUFDaEIsK0NBQStDO0lBRS9DOztPQUVHO0lBQ0gsT0FBTyxDQUFDLE1BQWMsRUFBRSxHQUFXO1FBQ2pDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNaLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUM1RSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDZixDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTLENBQUMsTUFBYztRQUN0QixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixPQUFPO1FBQ1QsQ0FBQztRQUNELE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDakUsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ2YsQ0FBQzsrR0F0R1UsY0FBYzttSEFBZCxjQUFjOzs0RkFBZCxjQUFjO2tCQUQxQixVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgc2lnbmFsIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB0eXBlIHsgRWRpdG9yIH0gZnJvbSBcIkB0aXB0YXAvY29yZVwiO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQXRlTGlua1NlcnZpY2Uge1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBTdGF0ZSBTaWduYWxzIChvd25lZCBieSB0aGlzIHNlcnZpY2UpXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqIFdoZXRoZXIgbGluayBlZGl0IG1vZGUgaXMgYWN0aXZlICovXG4gIHJlYWRvbmx5IGVkaXRNb2RlID0gc2lnbmFsPGJvb2xlYW4+KGZhbHNlKTtcblxuICAvKiogUmVmZXJlbmNlIHRvIHRoZSBlbGVtZW50IHRoYXQgdHJpZ2dlcmVkIHRoZSBtZW51IChmb3IgYW5jaG9yaW5nKSAqL1xuICByZWFkb25seSBtZW51VHJpZ2dlciA9IHNpZ25hbDxIVE1MRWxlbWVudCB8IG51bGw+KG51bGwpO1xuXG4gIC8qKiBXaGV0aGVyIHRoZSB1c2VyIGlzIGN1cnJlbnRseSBpbnRlcmFjdGluZyB3aXRoIHRoZSBsaW5rIFVJIChpbnB1dCBmb2N1cykgKi9cbiAgcmVhZG9ubHkgaXNJbnRlcmFjdGluZyA9IHNpZ25hbDxib29sZWFuPihmYWxzZSk7XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gTWVudSBMaWZlY3ljbGUgTWV0aG9kc1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBPcGVuIHRoZSBsaW5rIGVkaXQgbWVudS5cbiAgICovXG4gIG9wZW4odHJpZ2dlcj86IEhUTUxFbGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy5tZW51VHJpZ2dlci5zZXQodHJpZ2dlciB8fCBudWxsKTtcbiAgICB0aGlzLmVkaXRNb2RlLnNldCh0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZSB0aGUgbGluayBlZGl0IG1lbnUuXG4gICAqL1xuICBjbG9zZSgpOiB2b2lkIHtcbiAgICB0aGlzLmVkaXRNb2RlLnNldChmYWxzZSk7XG4gICAgdGhpcy5pc0ludGVyYWN0aW5nLnNldChmYWxzZSk7XG4gIH1cblxuICAvKipcbiAgICogRmluYWwgY2xlYW51cCAoY2FsbGVkIGFmdGVyIFVJIGlzIGhpZGRlbilcbiAgICovXG4gIGRvbmUoKTogdm9pZCB7XG4gICAgdGhpcy5tZW51VHJpZ2dlci5zZXQobnVsbCk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IGludGVyYWN0aW9uIHN0YXRlXG4gICAqL1xuICBzZXRJbnRlcmFjdGluZyh2YWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuaXNJbnRlcmFjdGluZy5zZXQodmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRvZ2dsZSBsaW5rIG1vZGUgZnJvbSBVSS5cbiAgICogSWYgYSBVUkwgc3RyaW5nIGlzIHByb3ZpZGVkLCBhcHBsaWVzIHRoZSBsaW5rIGFuZCBjbG9zZXMuXG4gICAqIElmIGFuIEV2ZW50IGlzIHByb3ZpZGVkLCBleHRyYWN0cyB0aGUgdHJpZ2dlciBmb3IgYW5jaG9yaW5nLlxuICAgKi9cbiAgdG9nZ2xlKGVkaXRvcjogRWRpdG9yLCB1cmxPckV2ZW50Pzogc3RyaW5nIHwgRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIWVkaXRvcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIElmIGEgc3RyaW5nIFVSTCBpcyBwcm92aWRlZCwgc2V0IHRoZSBsaW5rIGFuZCBjbG9zZVxuICAgIGlmICh1cmxPckV2ZW50ICYmIHR5cGVvZiB1cmxPckV2ZW50ID09PSBcInN0cmluZ1wiKSB7XG4gICAgICB0aGlzLnNldExpbmsoZWRpdG9yLCB1cmxPckV2ZW50KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBJZiBhbiBFdmVudCBpcyBwcm92aWRlZCwgZXh0cmFjdCB0aGUgdHJpZ2dlciBlbGVtZW50XG4gICAgbGV0IHRyaWdnZXI6IEhUTUxFbGVtZW50IHwgdW5kZWZpbmVkO1xuICAgIGlmICh1cmxPckV2ZW50ICYmIHR5cGVvZiB1cmxPckV2ZW50ICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICBjb25zdCB0YXJnZXQgPSAodXJsT3JFdmVudCBhcyBFdmVudCkudGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgICAgdHJpZ2dlciA9XG4gICAgICAgICgodXJsT3JFdmVudCBhcyBFdmVudCkuY3VycmVudFRhcmdldCBhcyBIVE1MRWxlbWVudCkgfHxcbiAgICAgICAgKHRhcmdldCBhcyBFbGVtZW50KT8uY2xvc2VzdChcImJ1dHRvblwiKSB8fFxuICAgICAgICB0YXJnZXQ7XG4gICAgfVxuXG4gICAgLy8gT3BlbiB0aGUgZWRpdCBtZW51XG4gICAgdGhpcy5vcGVuKHRyaWdnZXIpO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gTGluayBDb21tYW5kc1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBBcHBseSBhIGxpbmsgdG8gdGhlIGN1cnJlbnQgc2VsZWN0aW9uLlxuICAgKi9cbiAgc2V0TGluayhlZGl0b3I6IEVkaXRvciwgdXJsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIWVkaXRvcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBlZGl0b3IuY2hhaW4oKS5mb2N1cygpLmV4dGVuZE1hcmtSYW5nZShcImxpbmtcIikuc2V0TGluayh7IGhyZWY6IHVybCB9KS5ydW4oKTtcbiAgICB0aGlzLmNsb3NlKCk7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIGxpbmsgZnJvbSB0aGUgY3VycmVudCBzZWxlY3Rpb24uXG4gICAqL1xuICB1bnNldExpbmsoZWRpdG9yOiBFZGl0b3IpOiB2b2lkIHtcbiAgICBpZiAoIWVkaXRvcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBlZGl0b3IuY2hhaW4oKS5mb2N1cygpLmV4dGVuZE1hcmtSYW5nZShcImxpbmtcIikudW5zZXRMaW5rKCkucnVuKCk7XG4gICAgdGhpcy5jbG9zZSgpO1xuICB9XG59XG4iXX0=