@flogeez/angular-tiptap-editor 3.1.2 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +2 -2
- package/esm2022/flogeez-angular-tiptap-editor.mjs +5 -0
- package/esm2022/lib/ate-editor.provider.mjs +38 -0
- package/esm2022/lib/components/bubble-menus/base/ate-base-bubble-menu.mjs +207 -0
- package/esm2022/lib/components/bubble-menus/base/ate-base-sub-bubble-menu.mjs +137 -0
- package/esm2022/lib/components/bubble-menus/color/ate-color-bubble-menu.component.mjs +365 -0
- package/esm2022/lib/components/bubble-menus/image/ate-image-bubble-menu.component.mjs +309 -0
- package/esm2022/lib/components/bubble-menus/link/ate-link-bubble-menu.component.mjs +247 -0
- package/esm2022/lib/components/bubble-menus/table/ate-cell-bubble-menu.component.mjs +126 -0
- package/esm2022/lib/components/bubble-menus/table/ate-table-bubble-menu.component.mjs +271 -0
- package/esm2022/lib/components/bubble-menus/text/ate-bubble-menu.component.mjs +272 -0
- package/esm2022/lib/components/color-picker/ate-color-picker.component.mjs +123 -0
- package/esm2022/lib/components/edit-toggle/ate-edit-toggle.component.mjs +42 -0
- package/esm2022/lib/components/editor/angular-tiptap-editor.component.mjs +1031 -0
- package/esm2022/lib/components/editor/ate-block-controls.component.mjs +256 -0
- package/esm2022/lib/components/slash-commands/ate-slash-commands.component.mjs +328 -0
- package/esm2022/lib/components/toolbar/ate-toolbar.component.mjs +531 -0
- package/esm2022/lib/components/ui/ate-button.component.mjs +91 -0
- package/esm2022/lib/components/ui/ate-separator.component.mjs +11 -0
- package/esm2022/lib/config/ate-editor.config.mjs +133 -0
- package/esm2022/lib/config/ate-global-config.token.mjs +6 -0
- package/esm2022/lib/config/ate-slash-commands.config.mjs +130 -0
- package/esm2022/lib/directives/ate-noop-value-accessor.directive.mjs +40 -0
- package/esm2022/lib/directives/ate-tooltip.directive.mjs +138 -0
- package/esm2022/lib/extensions/ate-block-controls.extension.mjs +156 -0
- package/esm2022/lib/extensions/ate-link-click-behavior.extension.mjs +32 -0
- package/esm2022/lib/extensions/ate-resizable-image.extension.mjs +277 -0
- package/esm2022/lib/extensions/ate-table.extension.mjs +27 -0
- package/esm2022/lib/extensions/ate-tiptap-state.extension.mjs +85 -0
- package/esm2022/lib/extensions/ate-upload-progress.extension.mjs +195 -0
- package/esm2022/lib/extensions/calculators/ate-discovery.calculator.mjs +62 -0
- package/esm2022/lib/extensions/calculators/ate-image.calculator.mjs +8 -0
- package/esm2022/lib/extensions/calculators/ate-marks.calculator.mjs +75 -0
- package/esm2022/lib/extensions/calculators/ate-selection.calculator.mjs +35 -0
- package/esm2022/lib/extensions/calculators/ate-structure.calculator.mjs +34 -0
- package/esm2022/lib/extensions/calculators/ate-table.calculator.mjs +38 -0
- package/esm2022/lib/models/ate-bubble-menu.model.mjs +53 -0
- package/esm2022/lib/models/ate-editor-config.model.mjs +2 -0
- package/esm2022/lib/models/ate-editor-state.model.mjs +90 -0
- package/esm2022/lib/models/ate-image.model.mjs +2 -0
- package/esm2022/lib/models/ate-slash-command.model.mjs +2 -0
- package/esm2022/lib/models/ate-toolbar.model.mjs +35 -0
- package/esm2022/lib/node-view/ate-angular-node-view.mjs +97 -0
- package/esm2022/lib/node-view/ate-injector.registry.mjs +16 -0
- package/esm2022/lib/node-view/ate-node-view.factory.mjs +125 -0
- package/esm2022/lib/node-view/ate-node-view.models.mjs +2 -0
- package/esm2022/lib/node-view/ate-node-view.renderer.mjs +154 -0
- package/esm2022/lib/node-view/ate-register-angular-component.mjs +49 -0
- package/esm2022/lib/services/ate-color-picker.service.mjs +194 -0
- package/esm2022/lib/services/ate-editor-commands.service.mjs +474 -0
- package/esm2022/lib/services/ate-i18n.service.mjs +422 -0
- package/esm2022/lib/services/ate-image.service.mjs +459 -0
- package/esm2022/lib/services/ate-link.service.mjs +99 -0
- package/esm2022/lib/utils/ate-color.utils.mjs +60 -0
- package/esm2022/public-api.mjs +40 -0
- package/fesm2022/flogeez-angular-tiptap-editor.mjs +321 -354
- package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
- package/index.d.ts +3 -1734
- package/lib/ate-editor.provider.d.ts +21 -0
- package/lib/components/bubble-menus/base/ate-base-bubble-menu.d.ts +71 -0
- package/lib/components/bubble-menus/base/ate-base-sub-bubble-menu.d.ts +60 -0
- package/lib/components/bubble-menus/color/ate-color-bubble-menu.component.d.ts +77 -0
- package/lib/components/bubble-menus/image/ate-image-bubble-menu.component.d.ts +49 -0
- package/lib/components/bubble-menus/link/ate-link-bubble-menu.component.d.ts +55 -0
- package/lib/components/bubble-menus/table/ate-cell-bubble-menu.component.d.ts +16 -0
- package/lib/components/bubble-menus/table/ate-table-bubble-menu.component.d.ts +25 -0
- package/lib/components/bubble-menus/text/ate-bubble-menu.component.d.ts +53 -0
- package/lib/components/color-picker/ate-color-picker.component.d.ts +54 -0
- package/lib/components/edit-toggle/ate-edit-toggle.component.d.ts +13 -0
- package/lib/components/editor/angular-tiptap-editor.component.d.ts +242 -0
- package/lib/components/editor/ate-block-controls.component.d.ts +44 -0
- package/lib/components/slash-commands/ate-slash-commands.component.d.ts +34 -0
- package/lib/components/toolbar/ate-toolbar.component.d.ts +47 -0
- package/lib/components/ui/ate-button.component.d.ts +25 -0
- package/lib/components/ui/ate-separator.component.d.ts +5 -0
- package/lib/config/ate-editor.config.d.ts +19 -0
- package/lib/config/ate-global-config.token.d.ts +6 -0
- package/lib/config/ate-slash-commands.config.d.ts +41 -0
- package/lib/directives/ate-noop-value-accessor.directive.d.ts +13 -0
- package/lib/directives/ate-tooltip.directive.d.ts +30 -0
- package/lib/extensions/ate-block-controls.extension.d.ts +10 -0
- package/lib/extensions/ate-link-click-behavior.extension.d.ts +2 -0
- package/lib/extensions/ate-resizable-image.extension.d.ts +27 -0
- package/lib/extensions/ate-table.extension.d.ts +2 -0
- package/lib/extensions/ate-tiptap-state.extension.d.ts +7 -0
- package/lib/extensions/ate-upload-progress.extension.d.ts +7 -0
- package/lib/extensions/calculators/ate-discovery.calculator.d.ts +7 -0
- package/lib/extensions/calculators/ate-image.calculator.d.ts +2 -0
- package/lib/extensions/calculators/ate-marks.calculator.d.ts +2 -0
- package/lib/extensions/calculators/ate-selection.calculator.d.ts +2 -0
- package/lib/extensions/calculators/ate-structure.calculator.d.ts +2 -0
- package/lib/extensions/calculators/ate-table.calculator.d.ts +2 -0
- package/lib/models/ate-bubble-menu.model.d.ts +33 -0
- package/lib/models/ate-editor-config.model.d.ts +113 -0
- package/lib/models/ate-editor-state.model.d.ts +109 -0
- package/lib/models/ate-image.model.d.ts +104 -0
- package/lib/models/ate-slash-command.model.d.ts +17 -0
- package/lib/models/ate-toolbar.model.d.ts +18 -0
- package/lib/node-view/ate-angular-node-view.d.ts +115 -0
- package/lib/node-view/ate-injector.registry.d.ts +3 -0
- package/lib/node-view/ate-node-view.factory.d.ts +10 -0
- package/lib/node-view/ate-node-view.models.d.ts +138 -0
- package/lib/node-view/ate-node-view.renderer.d.ts +23 -0
- package/lib/node-view/ate-register-angular-component.d.ts +35 -0
- package/lib/services/ate-color-picker.service.d.ts +65 -0
- package/lib/services/ate-editor-commands.service.d.ts +75 -0
- package/lib/services/ate-i18n.service.d.ts +406 -0
- package/lib/services/ate-image.service.d.ts +82 -0
- package/lib/services/ate-link.service.d.ts +42 -0
- package/lib/utils/ate-color.utils.d.ts +12 -0
- package/package.json +3 -1
- package/public-api.d.ts +31 -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=
|