@flogeez/angular-tiptap-editor 2.3.0 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +132 -93
- 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 +133 -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 +226 -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 +121 -0
- package/esm2022/lib/components/bubble-menus/table/ate-table-bubble-menu.component.mjs +266 -0
- package/esm2022/lib/components/bubble-menus/text/ate-bubble-menu.component.mjs +294 -0
- package/esm2022/lib/components/color-picker/ate-color-picker.component.mjs +122 -0
- package/esm2022/lib/components/edit-toggle/ate-edit-toggle.component.mjs +42 -0
- package/esm2022/lib/components/editor/angular-tiptap-editor.component.mjs +953 -0
- package/esm2022/lib/components/slash-commands/ate-slash-commands.component.mjs +329 -0
- package/esm2022/lib/components/toolbar/ate-toolbar.component.mjs +531 -0
- package/esm2022/lib/components/ui/ate-button.component.mjs +90 -0
- package/esm2022/lib/components/ui/ate-separator.component.mjs +31 -0
- package/esm2022/lib/config/ate-editor.config.mjs +76 -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/extensions/ate-link-click-behavior.extension.mjs +32 -0
- package/esm2022/lib/extensions/ate-resizable-image.extension.mjs +270 -0
- package/esm2022/lib/extensions/ate-table.extension.mjs +29 -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 +49 -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-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 +193 -0
- package/esm2022/lib/services/ate-editor-commands.service.mjs +465 -0
- package/esm2022/lib/services/ate-i18n.service.mjs +410 -0
- package/esm2022/lib/services/ate-image.service.mjs +368 -0
- package/esm2022/lib/services/ate-link.service.mjs +97 -0
- package/esm2022/lib/utils/ate-color.utils.mjs +60 -0
- package/esm2022/public-api.mjs +93 -0
- package/fesm2022/flogeez-angular-tiptap-editor.mjs +1178 -1100
- package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
- package/index.d.ts +3 -1562
- 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 +52 -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 +12 -0
- package/lib/components/bubble-menus/table/ate-table-bubble-menu.component.d.ts +24 -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 +235 -0
- package/lib/components/slash-commands/ate-slash-commands.component.d.ts +43 -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 +7 -0
- package/lib/config/ate-editor.config.d.ts +7 -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/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 +100 -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-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 +72 -0
- package/lib/services/ate-i18n.service.d.ts +394 -0
- package/lib/services/ate-image.service.d.ts +71 -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 +112 -0
|
@@ -0,0 +1,368 @@
|
|
|
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
|
+
const { from } = editor.state.selection;
|
|
47
|
+
editor.chain().focus().setResizableImage(imageData).setNodeSelection(from).run();
|
|
48
|
+
}
|
|
49
|
+
/** Update attributes of the currently active image */
|
|
50
|
+
updateImageAttributes(editor, attributes) {
|
|
51
|
+
if (editor.isActive("resizableImage")) {
|
|
52
|
+
const pos = editor.state.selection.from;
|
|
53
|
+
editor
|
|
54
|
+
.chain()
|
|
55
|
+
.focus()
|
|
56
|
+
.updateAttributes("resizableImage", attributes)
|
|
57
|
+
.setNodeSelection(pos)
|
|
58
|
+
.run();
|
|
59
|
+
this.updateSelectedImage(attributes);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** Resize image with optional aspect ratio maintenance */
|
|
63
|
+
resizeImage(editor, options) {
|
|
64
|
+
if (!editor.isActive("resizableImage")) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const currentAttrs = editor.getAttributes("resizableImage");
|
|
68
|
+
let newWidth = options.width;
|
|
69
|
+
let newHeight = options.height;
|
|
70
|
+
// Maintain aspect ratio if requested
|
|
71
|
+
if (options.maintainAspectRatio !== false && currentAttrs["width"] && currentAttrs["height"]) {
|
|
72
|
+
const aspectRatio = currentAttrs["width"] / currentAttrs["height"];
|
|
73
|
+
if (newWidth && !newHeight) {
|
|
74
|
+
newHeight = Math.round(newWidth / aspectRatio);
|
|
75
|
+
}
|
|
76
|
+
else if (newHeight && !newWidth) {
|
|
77
|
+
newWidth = Math.round(newHeight * aspectRatio);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Apply minimum limits
|
|
81
|
+
if (newWidth) {
|
|
82
|
+
newWidth = Math.max(50, newWidth);
|
|
83
|
+
}
|
|
84
|
+
if (newHeight) {
|
|
85
|
+
newHeight = Math.max(50, newHeight);
|
|
86
|
+
}
|
|
87
|
+
this.updateImageAttributes(editor, {
|
|
88
|
+
width: newWidth,
|
|
89
|
+
height: newHeight,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/** Predetermined resize helpers used by UI */
|
|
93
|
+
resizeImageToSmall(editor) {
|
|
94
|
+
this.resizeImage(editor, { width: 300, height: 200, maintainAspectRatio: true });
|
|
95
|
+
}
|
|
96
|
+
resizeImageToMedium(editor) {
|
|
97
|
+
this.resizeImage(editor, { width: 500, height: 350, maintainAspectRatio: true });
|
|
98
|
+
}
|
|
99
|
+
resizeImageToLarge(editor) {
|
|
100
|
+
this.resizeImage(editor, { width: 800, height: 600, maintainAspectRatio: true });
|
|
101
|
+
}
|
|
102
|
+
resizeImageToOriginal(editor) {
|
|
103
|
+
if (!editor.isActive("resizableImage")) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const img = new Image();
|
|
107
|
+
img.onload = () => {
|
|
108
|
+
this.resizeImage(editor, { width: img.naturalWidth, height: img.naturalHeight });
|
|
109
|
+
};
|
|
110
|
+
img.src = editor.getAttributes("resizableImage")["src"];
|
|
111
|
+
}
|
|
112
|
+
/** Get current image dimensions */
|
|
113
|
+
getImageDimensions(editor) {
|
|
114
|
+
if (!editor.isActive("resizableImage")) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
const attrs = editor.getAttributes("resizableImage");
|
|
118
|
+
return {
|
|
119
|
+
width: attrs["width"] || 0,
|
|
120
|
+
height: attrs["height"] || 0,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/** Remove the selected image */
|
|
124
|
+
deleteImage(editor) {
|
|
125
|
+
if (editor.isActive("resizableImage")) {
|
|
126
|
+
editor.chain().focus().deleteSelection().run();
|
|
127
|
+
this.clearSelection();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
updateSelectedImage(attributes) {
|
|
131
|
+
const current = this.selectedImage();
|
|
132
|
+
if (current) {
|
|
133
|
+
this.selectedImage.set({ ...current, ...attributes });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/** Validate file type and size */
|
|
137
|
+
validateImage(file, options) {
|
|
138
|
+
const maxSize = options?.maxSize || 10 * 1024 * 1024;
|
|
139
|
+
const allowedTypes = options?.allowedTypes || [];
|
|
140
|
+
if (allowedTypes.length > 0 && !allowedTypes.includes(file.type)) {
|
|
141
|
+
return { valid: false, error: this.t().invalidFileType };
|
|
142
|
+
}
|
|
143
|
+
if (file.size > maxSize) {
|
|
144
|
+
return {
|
|
145
|
+
valid: false,
|
|
146
|
+
error: `${this.t().imageTooLarge} (max ${Math.round(maxSize / 1024 / 1024)}MB)`,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return { valid: true };
|
|
150
|
+
}
|
|
151
|
+
/** Compress and process image on client side */
|
|
152
|
+
async compressImage(file, quality = 0.8, maxWidth = 1920, maxHeight = 1200) {
|
|
153
|
+
return new Promise((resolve, reject) => {
|
|
154
|
+
const canvas = document.createElement("canvas");
|
|
155
|
+
const ctx = canvas.getContext("2d");
|
|
156
|
+
const img = new Image();
|
|
157
|
+
img.onload = () => {
|
|
158
|
+
if (this.isUploading()) {
|
|
159
|
+
this.uploadProgress.set(40);
|
|
160
|
+
this.uploadMessage.set(this.t().resizing);
|
|
161
|
+
}
|
|
162
|
+
let { width, height } = img;
|
|
163
|
+
if (width > maxWidth || height > maxHeight) {
|
|
164
|
+
const ratio = Math.min(maxWidth / width, maxHeight / height);
|
|
165
|
+
width *= ratio;
|
|
166
|
+
height *= ratio;
|
|
167
|
+
}
|
|
168
|
+
canvas.width = width;
|
|
169
|
+
canvas.height = height;
|
|
170
|
+
ctx?.drawImage(img, 0, 0, width, height);
|
|
171
|
+
if (this.isUploading()) {
|
|
172
|
+
this.uploadProgress.set(60);
|
|
173
|
+
this.uploadMessage.set(this.t().compressing);
|
|
174
|
+
}
|
|
175
|
+
canvas.toBlob(blob => {
|
|
176
|
+
if (blob) {
|
|
177
|
+
const reader = new FileReader();
|
|
178
|
+
reader.onload = e => {
|
|
179
|
+
const base64 = e.target?.result;
|
|
180
|
+
resolve({
|
|
181
|
+
src: base64,
|
|
182
|
+
name: file.name,
|
|
183
|
+
size: blob.size,
|
|
184
|
+
type: file.type,
|
|
185
|
+
width: Math.round(width),
|
|
186
|
+
height: Math.round(height),
|
|
187
|
+
originalSize: file.size,
|
|
188
|
+
});
|
|
189
|
+
};
|
|
190
|
+
reader.readAsDataURL(blob);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
reject(new Error(this.t().compressionError));
|
|
194
|
+
}
|
|
195
|
+
}, file.type, quality);
|
|
196
|
+
};
|
|
197
|
+
img.onerror = () => reject(new Error(this.t().loadError));
|
|
198
|
+
img.src = URL.createObjectURL(file);
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
/** Core upload logic with progress tracking */
|
|
202
|
+
async uploadImageWithProgress(editor, file, insertionStrategy, actionMessage, options) {
|
|
203
|
+
try {
|
|
204
|
+
this.currentEditor = editor;
|
|
205
|
+
this.isUploading.set(true);
|
|
206
|
+
this.uploadProgress.set(10);
|
|
207
|
+
this.uploadMessage.set(this.t().validating);
|
|
208
|
+
this.forceEditorUpdate();
|
|
209
|
+
const validation = this.validateImage(file, {
|
|
210
|
+
maxSize: options?.maxSize,
|
|
211
|
+
allowedTypes: options?.allowedTypes,
|
|
212
|
+
});
|
|
213
|
+
if (!validation.valid) {
|
|
214
|
+
throw new Error(validation.error);
|
|
215
|
+
}
|
|
216
|
+
this.uploadProgress.set(30);
|
|
217
|
+
this.uploadMessage.set(this.t().compressing);
|
|
218
|
+
this.forceEditorUpdate();
|
|
219
|
+
const result = await this.compressImage(file, options?.quality || 0.8, options?.maxWidth || 1920, options?.maxHeight || 1200);
|
|
220
|
+
this.uploadProgress.set(70);
|
|
221
|
+
// Handle custom upload if handler is provided
|
|
222
|
+
if (this.uploadHandler) {
|
|
223
|
+
this.uploadMessage.set(this.t().uploadingToServer);
|
|
224
|
+
this.forceEditorUpdate();
|
|
225
|
+
try {
|
|
226
|
+
const handlerResponse = this.uploadHandler({
|
|
227
|
+
file,
|
|
228
|
+
width: result.width || 0,
|
|
229
|
+
height: result.height || 0,
|
|
230
|
+
type: result.type,
|
|
231
|
+
base64: result.src,
|
|
232
|
+
});
|
|
233
|
+
const handlerResult = isObservable(handlerResponse)
|
|
234
|
+
? await firstValueFrom(handlerResponse)
|
|
235
|
+
: await handlerResponse;
|
|
236
|
+
result.src = handlerResult.src;
|
|
237
|
+
if (handlerResult.alt) {
|
|
238
|
+
result.name = handlerResult.alt;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
catch (handlerError) {
|
|
242
|
+
console.error(this.t().uploadError, handlerError);
|
|
243
|
+
throw handlerError;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
this.uploadProgress.set(90);
|
|
247
|
+
this.uploadMessage.set(actionMessage);
|
|
248
|
+
this.forceEditorUpdate();
|
|
249
|
+
// Final insertion
|
|
250
|
+
insertionStrategy(editor, result);
|
|
251
|
+
this.resetUploadState();
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
this.resetUploadState();
|
|
255
|
+
console.error(this.t().uploadError, error);
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
resetUploadState() {
|
|
260
|
+
this.isUploading.set(false);
|
|
261
|
+
this.uploadProgress.set(0);
|
|
262
|
+
this.uploadMessage.set("");
|
|
263
|
+
this.forceEditorUpdate();
|
|
264
|
+
this.currentEditor = null;
|
|
265
|
+
}
|
|
266
|
+
/** Main entry point for file upload and insertion */
|
|
267
|
+
async uploadAndInsertImage(editor, file, options) {
|
|
268
|
+
return this.uploadImageWithProgress(editor, file, (ed, result) => {
|
|
269
|
+
this.insertImage(ed, {
|
|
270
|
+
src: result.src,
|
|
271
|
+
alt: result.name,
|
|
272
|
+
title: `${result.name} (${result.width}×${result.height})`,
|
|
273
|
+
width: result.width,
|
|
274
|
+
height: result.height,
|
|
275
|
+
});
|
|
276
|
+
}, this.t().insertingImage, options);
|
|
277
|
+
}
|
|
278
|
+
/** Trigger an editor transaction to force decoration update */
|
|
279
|
+
forceEditorUpdate() {
|
|
280
|
+
if (this.currentEditor) {
|
|
281
|
+
const { tr } = this.currentEditor.state;
|
|
282
|
+
this.currentEditor.view.dispatch(tr);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/** Generic helper to open file picker and process selection */
|
|
286
|
+
async selectFileAndProcess(editor, uploadMethod, options) {
|
|
287
|
+
return new Promise((resolve, reject) => {
|
|
288
|
+
const input = document.createElement("input");
|
|
289
|
+
input.type = "file";
|
|
290
|
+
// Use allowedTypes if provided, otherwise default to image/*
|
|
291
|
+
if (options?.allowedTypes && options.allowedTypes.length > 0) {
|
|
292
|
+
input.accept = options.allowedTypes.join(",");
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
input.accept = "image/*";
|
|
296
|
+
}
|
|
297
|
+
input.style.display = "none";
|
|
298
|
+
input.addEventListener("change", async (e) => {
|
|
299
|
+
const file = e.target.files?.[0];
|
|
300
|
+
if (file && file.type.startsWith("image/")) {
|
|
301
|
+
try {
|
|
302
|
+
await uploadMethod(editor, file, options);
|
|
303
|
+
resolve();
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
reject(error);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
reject(new Error(this.t().noFileSelected));
|
|
311
|
+
}
|
|
312
|
+
document.body.removeChild(input);
|
|
313
|
+
});
|
|
314
|
+
input.addEventListener("cancel", () => {
|
|
315
|
+
document.body.removeChild(input);
|
|
316
|
+
reject(new Error(this.t().selectionCancelled));
|
|
317
|
+
});
|
|
318
|
+
document.body.appendChild(input);
|
|
319
|
+
input.click();
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
/** Select file and upload as new image */
|
|
323
|
+
async selectAndUploadImage(editor, options) {
|
|
324
|
+
return this.selectFileAndProcess(editor, this.uploadAndInsertImage.bind(this), options);
|
|
325
|
+
}
|
|
326
|
+
/** Select file and replace currently selected image */
|
|
327
|
+
async selectAndReplaceImage(editor, options) {
|
|
328
|
+
// No need for complicated backup/restore now that we don't delete prematurely.
|
|
329
|
+
// The uploadAndReplaceImage will handle the atomic replacement.
|
|
330
|
+
return this.selectFileAndProcess(editor, this.uploadAndReplaceImage.bind(this), options);
|
|
331
|
+
}
|
|
332
|
+
/** Internal helper used by replacement logic */
|
|
333
|
+
async uploadAndReplaceImage(editor, file, options) {
|
|
334
|
+
// Store current position to ensure we can re-select the image even if selection blurs during upload
|
|
335
|
+
const pos = editor.state.selection.from;
|
|
336
|
+
const wasActive = editor.isActive("resizableImage");
|
|
337
|
+
await this.uploadImageWithProgress(editor, file, (ed, result) => {
|
|
338
|
+
const imageData = {
|
|
339
|
+
src: result.src,
|
|
340
|
+
alt: result.name,
|
|
341
|
+
title: `${result.name} (${result.width}×${result.height})`,
|
|
342
|
+
width: result.width,
|
|
343
|
+
height: result.height,
|
|
344
|
+
};
|
|
345
|
+
// If the image was active or is still active, update it atomically
|
|
346
|
+
if (wasActive || ed.isActive("resizableImage")) {
|
|
347
|
+
ed.chain()
|
|
348
|
+
.focus()
|
|
349
|
+
.updateAttributes("resizableImage", imageData)
|
|
350
|
+
.setNodeSelection(pos)
|
|
351
|
+
.run();
|
|
352
|
+
this.updateSelectedImage(imageData);
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
// Otherwise replace whatever is selected (or insert at cursor)
|
|
356
|
+
this.insertImage(ed, imageData);
|
|
357
|
+
}
|
|
358
|
+
// After replacement, ensure the image is tracked in our signals
|
|
359
|
+
this.selectImage(ed);
|
|
360
|
+
}, this.t().replacingImage, options);
|
|
361
|
+
}
|
|
362
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
363
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageService }); }
|
|
364
|
+
}
|
|
365
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageService, decorators: [{
|
|
366
|
+
type: Injectable
|
|
367
|
+
}] });
|
|
368
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRlLWltYWdlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLXRpcHRhcC1lZGl0b3Ivc3JjL2xpYi9zZXJ2aWNlcy9hdGUtaW1hZ2Uuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRXJFLE9BQU8sRUFBRSxZQUFZLEVBQUUsY0FBYyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3BELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQzs7QUFVcEQsTUFBTSxPQUFPLGVBQWU7SUFENUI7UUFFRSw4QkFBOEI7UUFDOUIsa0JBQWEsR0FBRyxNQUFNLENBQXNCLElBQUksQ0FBQyxDQUFDO1FBQ2xELG9CQUFlLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsS0FBSyxJQUFJLENBQUMsQ0FBQztRQUVoRSxxQkFBcUI7UUFDckIsZUFBVSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUVuQixTQUFJLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3JCLE1BQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUUzQywyQkFBMkI7UUFDM0IsZ0JBQVcsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDNUIsbUJBQWMsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0Isa0JBQWEsR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFM0I7OztXQUdHO1FBQ0gsa0JBQWEsR0FBaUMsSUFBSSxDQUFDO1FBRTNDLGtCQUFhLEdBQWtCLElBQUksQ0FBQztLQThhN0M7SUE1YUMsZ0RBQWdEO0lBQ2hELFdBQVcsQ0FBQyxNQUFjO1FB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QUFTLElBQUksRUFBRSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUM7Z0JBQy9DLEVBQUUsQ0FBQyxLQUFLLEVBQUU7cUJBQ1AsS0FBSyxFQUFFO3FCQUNQLGdCQUFnQixDQUFDLGdCQUFnQixFQUFFLFNBQVMsQ0FBQztxQkFDN0MsZ0JBQWdCLENBQUMsR0FBRyxDQUFDO3FCQUNyQixHQUFHLEVBQUUsQ0FBQztnQkFDVCxJQUFJLENBQUMsbUJBQW1CLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDdEMsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLCtEQUErRDtnQkFDL0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxFQUFFLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFDbEMsQ0FBQztZQUVELGdFQUFnRTtZQUNoRSxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZCLENBQUMsRUFDRCxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsY0FBYyxFQUN2QixPQUFPLENBQ1IsQ0FBQztJQUNKLENBQUM7K0dBbmNVLGVBQWU7bUhBQWYsZUFBZTs7NEZBQWYsZUFBZTtrQkFEM0IsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIHNpZ25hbCwgY29tcHV0ZWQsIGluamVjdCB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBFZGl0b3IgfSBmcm9tIFwiQHRpcHRhcC9jb3JlXCI7XG5pbXBvcnQgeyBpc09ic2VydmFibGUsIGZpcnN0VmFsdWVGcm9tIH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IEF0ZUkxOG5TZXJ2aWNlIH0gZnJvbSBcIi4vYXRlLWkxOG4uc2VydmljZVwiO1xuaW1wb3J0IHtcbiAgQXRlUmVzaXplT3B0aW9ucyxcbiAgQXRlSW1hZ2VVcGxvYWRPcHRpb25zLFxuICBBdGVJbWFnZVVwbG9hZEhhbmRsZXIsXG4gIEF0ZUltYWdlVXBsb2FkUmVzdWx0LFxuICBBdGVJbWFnZURhdGEsXG59IGZyb20gXCIuLi9tb2RlbHMvYXRlLWltYWdlLm1vZGVsXCI7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBBdGVJbWFnZVNlcnZpY2Uge1xuICAvKiogU2lnbmFscyBmb3IgaW1hZ2Ugc3RhdGUgKi9cbiAgc2VsZWN0ZWRJbWFnZSA9IHNpZ25hbDxBdGVJbWFnZURhdGEgfCBudWxsPihudWxsKTtcbiAgaXNJbWFnZVNlbGVjdGVkID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5zZWxlY3RlZEltYWdlKCkgIT09IG51bGwpO1xuXG4gIC8qKiBSZXNpemluZyBzdGF0ZSAqL1xuICBpc1Jlc2l6aW5nID0gc2lnbmFsKGZhbHNlKTtcblxuICBwcml2YXRlIGkxOG4gPSBpbmplY3QoQXRlSTE4blNlcnZpY2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IHQgPSB0aGlzLmkxOG4uaW1hZ2VVcGxvYWQ7XG5cbiAgLyoqIFVwbG9hZCBzdGF0ZSBzaWduYWxzICovXG4gIGlzVXBsb2FkaW5nID0gc2lnbmFsKGZhbHNlKTtcbiAgdXBsb2FkUHJvZ3Jlc3MgPSBzaWduYWwoMCk7XG4gIHVwbG9hZE1lc3NhZ2UgPSBzaWduYWwoXCJcIik7XG5cbiAgLyoqXG4gICAqIEN1c3RvbSB1cGxvYWQgaGFuZGxlci5cbiAgICogSWYgc2V0LCB0aGlzIGhhbmRsZXIgcmVwbGFjZXMgdGhlIGRlZmF1bHQgYmFzZTY0IGNvbnZlcnNpb24uXG4gICAqL1xuICB1cGxvYWRIYW5kbGVyOiBBdGVJbWFnZVVwbG9hZEhhbmRsZXIgfCBudWxsID0gbnVsbDtcblxuICBwcml2YXRlIGN1cnJlbnRFZGl0b3I6IEVkaXRvciB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBTZWxlY3QgYW5kIHRyYWNrIGFuIGltYWdlIGZyb20gdGhlIGVkaXRvciAqL1xuICBzZWxlY3RJbWFnZShlZGl0b3I6IEVkaXRvcik6IHZvaWQge1xuICAgIGlmIChlZGl0b3IuaXNBY3RpdmUoXCJyZXNpemFibGVJbWFnZVwiKSkge1xuICAgICAgY29uc3QgYXR0cnMgPSBlZGl0b3IuZ2V0QXR0cmlidXRlcyhcInJlc2l6YWJsZUltYWdlXCIpO1xuICAgICAgdGhpcy5zZWxlY3RlZEltYWdlLnNldCh7XG4gICAgICAgIHNyYzogYXR0cnNbXCJzcmNcIl0sXG4gICAgICAgIGFsdDogYXR0cnNbXCJhbHRcIl0sXG4gICAgICAgIHRpdGxlOiBhdHRyc1tcInRpdGxlXCJdLFxuICAgICAgICB3aWR0aDogYXR0cnNbXCJ3aWR0aFwiXSxcbiAgICAgICAgaGVpZ2h0OiBhdHRyc1tcImhlaWdodFwiXSxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnNlbGVjdGVkSW1hZ2Uuc2V0KG51bGwpO1xuICAgIH1cbiAgfVxuXG4gIGNsZWFyU2VsZWN0aW9uKCk6IHZvaWQge1xuICAgIHRoaXMuc2VsZWN0ZWRJbWFnZS5zZXQobnVsbCk7XG4gIH1cblxuICAvKiogSW5zZXJ0IGEgbmV3IGltYWdlIGFuZCBlbnN1cmUgaXQncyBzZWxlY3RlZCAqL1xuICBpbnNlcnRJbWFnZShlZGl0b3I6IEVkaXRvciwgaW1hZ2VEYXRhOiBBdGVJbWFnZURhdGEpOiB2b2lkIHtcbiAgICBjb25zdCB7IGZyb20gfSA9IGVkaXRvci5zdGF0ZS5zZWxlY3Rpb247XG4gICAgZWRpdG9yLmNoYWluKCkuZm9jdXMoKS5zZXRSZXNpemFibGVJbWFnZShpbWFnZURhdGEpLnNldE5vZGVTZWxlY3Rpb24oZnJvbSkucnVuKCk7XG4gIH1cblxuICAvKiogVXBkYXRlIGF0dHJpYnV0ZXMgb2YgdGhlIGN1cnJlbnRseSBhY3RpdmUgaW1hZ2UgKi9cbiAgdXBkYXRlSW1hZ2VBdHRyaWJ1dGVzKGVkaXRvcjogRWRpdG9yLCBhdHRyaWJ1dGVzOiBQYXJ0aWFsPEF0ZUltYWdlRGF0YT4pOiB2b2lkIHtcbiAgICBpZiAoZWRpdG9yLmlzQWN0aXZlKFwicmVzaXphYmxlSW1hZ2VcIikpIHtcbiAgICAgIGNvbnN0IHBvcyA9IGVkaXRvci5zdGF0ZS5zZWxlY3Rpb24uZnJvbTtcbiAgICAgIGVkaXRvclxuICAgICAgICAuY2hhaW4oKVxuICAgICAgICAuZm9jdXMoKVxuICAgICAgICAudXBkYXRlQXR0cmlidXRlcyhcInJlc2l6YWJsZUltYWdlXCIsIGF0dHJpYnV0ZXMpXG4gICAgICAgIC5zZXROb2RlU2VsZWN0aW9uKHBvcylcbiAgICAgICAgLnJ1bigpO1xuICAgICAgdGhpcy51cGRhdGVTZWxlY3RlZEltYWdlKGF0dHJpYnV0ZXMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBSZXNpemUgaW1hZ2Ugd2l0aCBvcHRpb25hbCBhc3BlY3QgcmF0aW8gbWFpbnRlbmFuY2UgKi9cbiAgcmVzaXplSW1hZ2UoZWRpdG9yOiBFZGl0b3IsIG9wdGlvbnM6IEF0ZVJlc2l6ZU9wdGlvbnMpOiB2b2lkIHtcbiAgICBpZiAoIWVkaXRvci5pc0FjdGl2ZShcInJlc2l6YWJsZUltYWdlXCIpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgY3VycmVudEF0dHJzID0gZWRpdG9yLmdldEF0dHJpYnV0ZXMoXCJyZXNpemFibGVJbWFnZVwiKTtcbiAgICBsZXQgbmV3V2lkdGggPSBvcHRpb25zLndpZHRoO1xuICAgIGxldCBuZXdIZWlnaHQgPSBvcHRpb25zLmhlaWdodDtcblxuICAgIC8vIE1haW50YWluIGFzcGVjdCByYXRpbyBpZiByZXF1ZXN0ZWRcbiAgICBpZiAob3B0aW9ucy5tYWludGFpbkFzcGVjdFJhdGlvICE9PSBmYWxzZSAmJiBjdXJyZW50QXR0cnNbXCJ3aWR0aFwiXSAmJiBjdXJyZW50QXR0cnNbXCJoZWlnaHRcIl0pIHtcbiAgICAgIGNvbnN0IGFzcGVjdFJhdGlvID0gY3VycmVudEF0dHJzW1wid2lkdGhcIl0gLyBjdXJyZW50QXR0cnNbXCJoZWlnaHRcIl07XG5cbiAgICAgIGlmIChuZXdXaWR0aCAmJiAhbmV3SGVpZ2h0KSB7XG4gICAgICAgIG5ld0hlaWdodCA9IE1hdGgucm91bmQobmV3V2lkdGggLyBhc3BlY3RSYXRpbyk7XG4gICAgICB9IGVsc2UgaWYgKG5ld0hlaWdodCAmJiAhbmV3V2lkdGgpIHtcbiAgICAgICAgbmV3V2lkdGggPSBNYXRoLnJvdW5kKG5ld0hlaWdodCAqIGFzcGVjdFJhdGlvKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBcHBseSBtaW5pbXVtIGxpbWl0c1xuICAgIGlmIChuZXdXaWR0aCkge1xuICAgICAgbmV3V2lkdGggPSBNYXRoLm1heCg1MCwgbmV3V2lkdGgpO1xuICAgIH1cbiAgICBpZiAobmV3SGVpZ2h0KSB7XG4gICAgICBuZXdIZWlnaHQgPSBNYXRoLm1heCg1MCwgbmV3SGVpZ2h0KTtcbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZUltYWdlQXR0cmlidXRlcyhlZGl0b3IsIHtcbiAgICAgIHdpZHRoOiBuZXdXaWR0aCxcbiAgICAgIGhlaWdodDogbmV3SGVpZ2h0LFxuICAgIH0pO1xuICB9XG5cbiAgLyoqIFByZWRldGVybWluZWQgcmVzaXplIGhlbHBlcnMgdXNlZCBieSBVSSAqL1xuICByZXNpemVJbWFnZVRvU21hbGwoZWRpdG9yOiBFZGl0b3IpOiB2b2lkIHtcbiAgICB0aGlzLnJlc2l6ZUltYWdlKGVkaXRvciwgeyB3aWR0aDogMzAwLCBoZWlnaHQ6IDIwMCwgbWFpbnRhaW5Bc3BlY3RSYXRpbzogdHJ1ZSB9KTtcbiAgfVxuXG4gIHJlc2l6ZUltYWdlVG9NZWRpdW0oZWRpdG9yOiBFZGl0b3IpOiB2b2lkIHtcbiAgICB0aGlzLnJlc2l6ZUltYWdlKGVkaXRvciwgeyB3aWR0aDogNTAwLCBoZWlnaHQ6IDM1MCwgbWFpbnRhaW5Bc3BlY3RSYXRpbzogdHJ1ZSB9KTtcbiAgfVxuXG4gIHJlc2l6ZUltYWdlVG9MYXJnZShlZGl0b3I6IEVkaXRvcik6IHZvaWQge1xuICAgIHRoaXMucmVzaXplSW1hZ2UoZWRpdG9yLCB7IHdpZHRoOiA4MDAsIGhlaWdodDogNjAwLCBtYWludGFpbkFzcGVjdFJhdGlvOiB0cnVlIH0pO1xuICB9XG5cbiAgcmVzaXplSW1hZ2VUb09yaWdpbmFsKGVkaXRvcjogRWRpdG9yKTogdm9pZCB7XG4gICAgaWYgKCFlZGl0b3IuaXNBY3RpdmUoXCJyZXNpemFibGVJbWFnZVwiKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICBpbWcub25sb2FkID0gKCkgPT4ge1xuICAgICAgdGhpcy5yZXNpemVJbWFnZShlZGl0b3IsIHsgd2lkdGg6IGltZy5uYXR1cmFsV2lkdGgsIGhlaWdodDogaW1nLm5hdHVyYWxIZWlnaHQgfSk7XG4gICAgfTtcbiAgICBpbWcuc3JjID0gZWRpdG9yLmdldEF0dHJpYnV0ZXMoXCJyZXNpemFibGVJbWFnZVwiKVtcInNyY1wiXTtcbiAgfVxuXG4gIC8qKiBHZXQgY3VycmVudCBpbWFnZSBkaW1lbnNpb25zICovXG4gIGdldEltYWdlRGltZW5zaW9ucyhlZGl0b3I6IEVkaXRvcik6IHsgd2lkdGg6IG51bWJlcjsgaGVpZ2h0OiBudW1iZXIgfSB8IG51bGwge1xuICAgIGlmICghZWRpdG9yLmlzQWN0aXZlKFwicmVzaXphYmxlSW1hZ2VcIikpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCBhdHRycyA9IGVkaXRvci5nZXRBdHRyaWJ1dGVzKFwicmVzaXphYmxlSW1hZ2VcIik7XG4gICAgcmV0dXJuIHtcbiAgICAgIHdpZHRoOiBhdHRyc1tcIndpZHRoXCJdIHx8IDAsXG4gICAgICBoZWlnaHQ6IGF0dHJzW1wiaGVpZ2h0XCJdIHx8IDAsXG4gICAgfTtcbiAgfVxuXG4gIC8qKiBSZW1vdmUgdGhlIHNlbGVjdGVkIGltYWdlICovXG4gIGRlbGV0ZUltYWdlKGVkaXRvcjogRWRpdG9yKTogdm9pZCB7XG4gICAgaWYgKGVkaXRvci5pc0FjdGl2ZShcInJlc2l6YWJsZUltYWdlXCIpKSB7XG4gICAgICBlZGl0b3IuY2hhaW4oKS5mb2N1cygpLmRlbGV0ZVNlbGVjdGlvbigpLnJ1bigpO1xuICAgICAgdGhpcy5jbGVhclNlbGVjdGlvbigpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlU2VsZWN0ZWRJbWFnZShhdHRyaWJ1dGVzOiBQYXJ0aWFsPEF0ZUltYWdlRGF0YT4pOiB2b2lkIHtcbiAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5zZWxlY3RlZEltYWdlKCk7XG4gICAgaWYgKGN1cnJlbnQpIHtcbiAgICAgIHRoaXMuc2VsZWN0ZWRJbWFnZS5zZXQoeyAuLi5jdXJyZW50LCAuLi5hdHRyaWJ1dGVzIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBWYWxpZGF0ZSBmaWxlIHR5cGUgYW5kIHNpemUgKi9cbiAgdmFsaWRhdGVJbWFnZShcbiAgICBmaWxlOiBGaWxlLFxuICAgIG9wdGlvbnM/OiB7IG1heFNpemU/OiBudW1iZXI7IGFsbG93ZWRUeXBlcz86IHN0cmluZ1tdIH1cbiAgKTogeyB2YWxpZDogYm9vbGVhbjsgZXJyb3I/OiBzdHJpbmcgfSB7XG4gICAgY29uc3QgbWF4U2l6ZSA9IG9wdGlvbnM/Lm1heFNpemUgfHwgMTAgKiAxMDI0ICogMTAyNDtcbiAgICBjb25zdCBhbGxvd2VkVHlwZXMgPSBvcHRpb25zPy5hbGxvd2VkVHlwZXMgfHwgW107XG5cbiAgICBpZiAoYWxsb3dlZFR5cGVzLmxlbmd0aCA+IDAgJiYgIWFsbG93ZWRUeXBlcy5pbmNsdWRlcyhmaWxlLnR5cGUpKSB7XG4gICAgICByZXR1cm4geyB2YWxpZDogZmFsc2UsIGVycm9yOiB0aGlzLnQoKS5pbnZhbGlkRmlsZVR5cGUgfTtcbiAgICB9XG5cbiAgICBpZiAoZmlsZS5zaXplID4gbWF4U2l6ZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmFsaWQ6IGZhbHNlLFxuICAgICAgICBlcnJvcjogYCR7dGhpcy50KCkuaW1hZ2VUb29MYXJnZX0gKG1heCAke01hdGgucm91bmQobWF4U2l6ZSAvIDEwMjQgLyAxMDI0KX1NQilgLFxuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHsgdmFsaWQ6IHRydWUgfTtcbiAgfVxuXG4gIC8qKiBDb21wcmVzcyBhbmQgcHJvY2VzcyBpbWFnZSBvbiBjbGllbnQgc2lkZSAqL1xuICBhc3luYyBjb21wcmVzc0ltYWdlKFxuICAgIGZpbGU6IEZpbGUsXG4gICAgcXVhbGl0eSA9IDAuOCxcbiAgICBtYXhXaWR0aCA9IDE5MjAsXG4gICAgbWF4SGVpZ2h0ID0gMTIwMFxuICApOiBQcm9taXNlPEF0ZUltYWdlVXBsb2FkUmVzdWx0PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJjYW52YXNcIik7XG4gICAgICBjb25zdCBjdHggPSBjYW52YXMuZ2V0Q29udGV4dChcIjJkXCIpO1xuICAgICAgY29uc3QgaW1nID0gbmV3IEltYWdlKCk7XG5cbiAgICAgIGltZy5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLmlzVXBsb2FkaW5nKCkpIHtcbiAgICAgICAgICB0aGlzLnVwbG9hZFByb2dyZXNzLnNldCg0MCk7XG4gICAgICAgICAgdGhpcy51cGxvYWRNZXNzYWdlLnNldCh0aGlzLnQoKS5yZXNpemluZyk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgeyB3aWR0aCwgaGVpZ2h0IH0gPSBpbWc7XG4gICAgICAgIGlmICh3aWR0aCA+IG1heFdpZHRoIHx8IGhlaWdodCA+IG1heEhlaWdodCkge1xuICAgICAgICAgIGNvbnN0IHJhdGlvID0gTWF0aC5taW4obWF4V2lkdGggLyB3aWR0aCwgbWF4SGVpZ2h0IC8gaGVpZ2h0KTtcbiAgICAgICAgICB3aWR0aCAqPSByYXRpbztcbiAgICAgICAgICBoZWlnaHQgKj0gcmF0aW87XG4gICAgICAgIH1cblxuICAgICAgICBjYW52YXMud2lkdGggPSB3aWR0aDtcbiAgICAgICAgY2FudmFzLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgY3R4Py5kcmF3SW1hZ2UoaW1nLCAwLCAwLCB3aWR0aCwgaGVpZ2h0KTtcblxuICAgICAgICBpZiAodGhpcy5pc1VwbG9hZGluZygpKSB7XG4gICAgICAgICAgdGhpcy51cGxvYWRQcm9ncmVzcy5zZXQoNjApO1xuICAgICAgICAgIHRoaXMudXBsb2FkTWVzc2FnZS5zZXQodGhpcy50KCkuY29tcHJlc3NpbmcpO1xuICAgICAgICB9XG5cbiAgICAgICAgY2FudmFzLnRvQmxvYihcbiAgICAgICAgICBibG9iID0+IHtcbiAgICAgICAgICAgIGlmIChibG9iKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XG4gICAgICAgICAgICAgIHJlYWRlci5vbmxvYWQgPSBlID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBiYXNlNjQgPSBlLnRhcmdldD8ucmVzdWx0IGFzIHN0cmluZztcbiAgICAgICAgICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICAgICAgICAgIHNyYzogYmFzZTY0LFxuICAgICAgICAgICAgICAgICAgbmFtZTogZmlsZS5uYW1lLFxuICAgICAgICAgICAgICAgICAgc2l6ZTogYmxvYi5zaXplLFxuICAgICAgICAgICAgICAgICAgdHlwZTogZmlsZS50eXBlLFxuICAgICAgICAgICAgICAgICAgd2lkdGg6IE1hdGgucm91bmQod2lkdGgpLFxuICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBNYXRoLnJvdW5kKGhlaWdodCksXG4gICAgICAgICAgICAgICAgICBvcmlnaW5hbFNpemU6IGZpbGUuc2l6ZSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgcmVhZGVyLnJlYWRBc0RhdGFVUkwoYmxvYik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKHRoaXMudCgpLmNvbXByZXNzaW9uRXJyb3IpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIGZpbGUudHlwZSxcbiAgICAgICAgICBxdWFsaXR5XG4gICAgICAgICk7XG4gICAgICB9O1xuXG4gICAgICBpbWcub25lcnJvciA9ICgpID0+IHJlamVjdChuZXcgRXJyb3IodGhpcy50KCkubG9hZEVycm9yKSk7XG4gICAgICBpbWcuc3JjID0gVVJMLmNyZWF0ZU9iamVjdFVSTChmaWxlKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBDb3JlIHVwbG9hZCBsb2dpYyB3aXRoIHByb2dyZXNzIHRyYWNraW5nICovXG4gIHByaXZhdGUgYXN5bmMgdXBsb2FkSW1hZ2VXaXRoUHJvZ3Jlc3MoXG4gICAgZWRpdG9yOiBFZGl0b3IsXG4gICAgZmlsZTogRmlsZSxcbiAgICBpbnNlcnRpb25TdHJhdGVneTogKGVkaXRvcjogRWRpdG9yLCByZXN1bHQ6IEF0ZUltYWdlVXBsb2FkUmVzdWx0KSA9PiB2b2lkLFxuICAgIGFjdGlvbk1lc3NhZ2U6IHN0cmluZyxcbiAgICBvcHRpb25zPzogQXRlSW1hZ2VVcGxvYWRPcHRpb25zXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLmN1cnJlbnRFZGl0b3IgPSBlZGl0b3I7XG4gICAgICB0aGlzLmlzVXBsb2FkaW5nLnNldCh0cnVlKTtcbiAgICAgIHRoaXMudXBsb2FkUHJvZ3Jlc3Muc2V0KDEwKTtcbiAgICAgIHRoaXMudXBsb2FkTWVzc2FnZS5zZXQodGhpcy50KCkudmFsaWRhdGluZyk7XG4gICAgICB0aGlzLmZvcmNlRWRpdG9yVXBkYXRlKCk7XG5cbiAgICAgIGNvbnN0IHZhbGlkYXRpb24gPSB0aGlzLnZhbGlkYXRlSW1hZ2UoZmlsZSwge1xuICAgICAgICBtYXhTaXplOiBvcHRpb25zPy5tYXhTaXplLFxuICAgICAgICBhbGxvd2VkVHlwZXM6IG9wdGlvbnM/LmFsbG93ZWRUeXBlcyxcbiAgICAgIH0pO1xuICAgICAgaWYgKCF2YWxpZGF0aW9uLnZhbGlkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcih2YWxpZGF0aW9uLmVycm9yKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy51cGxvYWRQcm9ncmVzcy5zZXQoMzApO1xuICAgICAgdGhpcy51cGxvYWRNZXNzYWdlLnNldCh0aGlzLnQoKS5jb21wcmVzc2luZyk7XG4gICAgICB0aGlzLmZvcmNlRWRpdG9yVXBkYXRlKCk7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuY29tcHJlc3NJbWFnZShcbiAgICAgICAgZmlsZSxcbiAgICAgICAgb3B0aW9ucz8ucXVhbGl0eSB8fCAwLjgsXG4gICAgICAgIG9wdGlvbnM/Lm1heFdpZHRoIHx8IDE5MjAsXG4gICAgICAgIG9wdGlvbnM/Lm1heEhlaWdodCB8fCAxMjAwXG4gICAgICApO1xuXG4gICAgICB0aGlzLnVwbG9hZFByb2dyZXNzLnNldCg3MCk7XG5cbiAgICAgIC8vIEhhbmRsZSBjdXN0b20gdXBsb2FkIGlmIGhhbmRsZXIgaXMgcHJvdmlkZWRcbiAgICAgIGlmICh0aGlzLnVwbG9hZEhhbmRsZXIpIHtcbiAgICAgICAgdGhpcy51cGxvYWRNZXNzYWdlLnNldCh0aGlzLnQoKS51cGxvYWRpbmdUb1NlcnZlcik7XG4gICAgICAgIHRoaXMuZm9yY2VFZGl0b3JVcGRhdGUoKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGhhbmRsZXJSZXNwb25zZSA9IHRoaXMudXBsb2FkSGFuZGxlcih7XG4gICAgICAgICAgICBmaWxlLFxuICAgICAgICAgICAgd2lkdGg6IHJlc3VsdC53aWR0aCB8fCAwLFxuICAgICAgICAgICAgaGVpZ2h0OiByZXN1bHQuaGVpZ2h0IHx8IDAsXG4gICAgICAgICAgICB0eXBlOiByZXN1bHQudHlwZSxcbiAgICAgICAgICAgIGJhc2U2NDogcmVzdWx0LnNyYyxcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGNvbnN0IGhhbmRsZXJSZXN1bHQgPSBpc09ic2VydmFibGUoaGFuZGxlclJlc3BvbnNlKVxuICAgICAgICAgICAgPyBhd2FpdCBmaXJzdFZhbHVlRnJvbShoYW5kbGVyUmVzcG9uc2UpXG4gICAgICAgICAgICA6IGF3YWl0IGhhbmRsZXJSZXNwb25zZTtcblxuICAgICAgICAgIHJlc3VsdC5zcmMgPSBoYW5kbGVyUmVzdWx0LnNyYztcbiAgICAgICAgICBpZiAoaGFuZGxlclJlc3VsdC5hbHQpIHtcbiAgICAgICAgICAgIHJlc3VsdC5uYW1lID0gaGFuZGxlclJlc3VsdC5hbHQ7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChoYW5kbGVyRXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKHRoaXMudCgpLnVwbG9hZEVycm9yLCBoYW5kbGVyRXJyb3IpO1xuICAgICAgICAgIHRocm93IGhhbmRsZXJFcnJvcjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aGlzLnVwbG9hZFByb2dyZXNzLnNldCg5MCk7XG4gICAgICB0aGlzLnVwbG9hZE1lc3NhZ2Uuc2V0KGFjdGlvbk1lc3NhZ2UpO1xuICAgICAgdGhpcy5mb3JjZUVkaXRvclVwZGF0ZSgpO1xuXG4gICAgICAvLyBGaW5hbCBpbnNlcnRpb25cbiAgICAgIGluc2VydGlvblN0cmF0ZWd5KGVkaXRvciwgcmVzdWx0KTtcblxuICAgICAgdGhpcy5yZXNldFVwbG9hZFN0YXRlKCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMucmVzZXRVcGxvYWRTdGF0ZSgpO1xuICAgICAgY29uc29sZS5lcnJvcih0aGlzLnQoKS51cGxvYWRFcnJvciwgZXJyb3IpO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZXNldFVwbG9hZFN0YXRlKCkge1xuICAgIHRoaXMuaXNVcGxvYWRpbmcuc2V0KGZhbHNlKTtcbiAgICB0aGlzLnVwbG9hZFByb2dyZXNzLnNldCgwKTtcbiAgICB0aGlzLnVwbG9hZE1lc3NhZ2Uuc2V0KFwiXCIpO1xuICAgIHRoaXMuZm9yY2VFZGl0b3JVcGRhdGUoKTtcbiAgICB0aGlzLmN1cnJlbnRFZGl0b3IgPSBudWxsO1xuICB9XG5cbiAgLyoqIE1haW4gZW50cnkgcG9pbnQgZm9yIGZpbGUgdXBsb2FkIGFuZCBpbnNlcnRpb24gKi9cbiAgYXN5bmMgdXBsb2FkQW5kSW5zZXJ0SW1hZ2UoXG4gICAgZWRpdG9yOiBFZGl0b3IsXG4gICAgZmlsZTogRmlsZSxcbiAgICBvcHRpb25zPzogQXRlSW1hZ2VVcGxvYWRPcHRpb25zXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLnVwbG9hZEltYWdlV2l0aFByb2dyZXNzKFxuICAgICAgZWRpdG9yLFxuICAgICAgZmlsZSxcbiAgICAgIChlZCwgcmVzdWx0KSA9PiB7XG4gICAgICAgIHRoaXMuaW5zZXJ0SW1hZ2UoZWQsIHtcbiAgICAgICAgICBzcmM6IHJlc3VsdC5zcmMsXG4gICAgICAgICAgYWx0OiByZXN1bHQubmFtZSxcbiAgICAgICAgICB0aXRsZTogYCR7cmVzdWx0Lm5hbWV9ICgke3Jlc3VsdC53aWR0aH3DlyR7cmVzdWx0LmhlaWdodH0pYCxcbiAgICAgICAgICB3aWR0aDogcmVzdWx0LndpZHRoLFxuICAgICAgICAgIGhlaWdodDogcmVzdWx0LmhlaWdodCxcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgICAgdGhpcy50KCkuaW5zZXJ0aW5nSW1hZ2UsXG4gICAgICBvcHRpb25zXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBUcmlnZ2VyIGFuIGVkaXRvciB0cmFuc2FjdGlvbiB0byBmb3JjZSBkZWNvcmF0aW9uIHVwZGF0ZSAqL1xuICBwcml2YXRlIGZvcmNlRWRpdG9yVXBkYXRlKCkge1xuICAgIGlmICh0aGlzLmN1cnJlbnRFZGl0b3IpIHtcbiAgICAgIGNvbnN0IHsgdHIgfSA9IHRoaXMuY3VycmVudEVkaXRvci5zdGF0ZTtcbiAgICAgIHRoaXMuY3VycmVudEVkaXRvci52aWV3LmRpc3BhdGNoKHRyKTtcbiAgICB9XG4gIH1cblxuICAvKiogR2VuZXJpYyBoZWxwZXIgdG8gb3BlbiBmaWxlIHBpY2tlciBhbmQgcHJvY2VzcyBzZWxlY3Rpb24gKi9cbiAgcHJpdmF0ZSBhc3luYyBzZWxlY3RGaWxlQW5kUHJvY2VzcyhcbiAgICBlZGl0b3I6IEVkaXRvcixcbiAgICB1cGxvYWRNZXRob2Q6IChlZGl0b3I6IEVkaXRvciwgZmlsZTogRmlsZSwgb3B0aW9ucz86IEF0ZUltYWdlVXBsb2FkT3B0aW9ucykgPT4gUHJvbWlzZTx2b2lkPixcbiAgICBvcHRpb25zPzogQXRlSW1hZ2VVcGxvYWRPcHRpb25zXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJpbnB1dFwiKTtcbiAgICAgIGlucHV0LnR5cGUgPSBcImZpbGVcIjtcblxuICAgICAgLy8gVXNlIGFsbG93ZWRUeXBlcyBpZiBwcm92aWRlZCwgb3RoZXJ3aXNlIGRlZmF1bHQgdG8gaW1hZ2UvKlxuICAgICAgaWYgKG9wdGlvbnM/LmFsbG93ZWRUeXBlcyAmJiBvcHRpb25zLmFsbG93ZWRUeXBlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGlucHV0LmFjY2VwdCA9IG9wdGlvbnMuYWxsb3dlZFR5cGVzLmpvaW4oXCIsXCIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5wdXQuYWNjZXB0ID0gXCJpbWFnZS8qXCI7XG4gICAgICB9XG5cbiAgICAgIGlucHV0LnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcblxuICAgICAgaW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImNoYW5nZVwiLCBhc3luYyBlID0+IHtcbiAgICAgICAgY29uc3QgZmlsZSA9IChlLnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS5maWxlcz8uWzBdO1xuICAgICAgICBpZiAoZmlsZSAmJiBmaWxlLnR5cGUuc3RhcnRzV2l0aChcImltYWdlL1wiKSkge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB1cGxvYWRNZXRob2QoZWRpdG9yLCBmaWxlLCBvcHRpb25zKTtcbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcih0aGlzLnQoKS5ub0ZpbGVTZWxlY3RlZCkpO1xuICAgICAgICB9XG4gICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoaW5wdXQpO1xuICAgICAgfSk7XG5cbiAgICAgIGlucHV0LmFkZEV2ZW50TGlzdGVuZXIoXCJjYW5jZWxcIiwgKCkgPT4ge1xuICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGlucHV0KTtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcih0aGlzLnQoKS5zZWxlY3Rpb25DYW5jZWxsZWQpKTtcbiAgICAgIH0pO1xuXG4gICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGlucHV0KTtcbiAgICAgIGlucHV0LmNsaWNrKCk7XG4gICAgfSk7XG4gIH1cblxuICAvKiogU2VsZWN0IGZpbGUgYW5kIHVwbG9hZCBhcyBuZXcgaW1hZ2UgKi9cbiAgYXN5bmMgc2VsZWN0QW5kVXBsb2FkSW1hZ2UoZWRpdG9yOiBFZGl0b3IsIG9wdGlvbnM/OiBBdGVJbWFnZVVwbG9hZE9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3RGaWxlQW5kUHJvY2VzcyhlZGl0b3IsIHRoaXMudXBsb2FkQW5kSW5zZXJ0SW1hZ2UuYmluZCh0aGlzKSwgb3B0aW9ucyk7XG4gIH1cblxuICAvKiogU2VsZWN0IGZpbGUgYW5kIHJlcGxhY2UgY3VycmVudGx5IHNlbGVjdGVkIGltYWdlICovXG4gIGFzeW5jIHNlbGVjdEFuZFJlcGxhY2VJbWFnZShlZGl0b3I6IEVkaXRvciwgb3B0aW9ucz86IEF0ZUltYWdlVXBsb2FkT3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIE5vIG5lZWQgZm9yIGNvbXBsaWNhdGVkIGJhY2t1cC9yZXN0b3JlIG5vdyB0aGF0IHdlIGRvbid0IGRlbGV0ZSBwcmVtYXR1cmVseS5cbiAgICAvLyBUaGUgdXBsb2FkQW5kUmVwbGFjZUltYWdlIHdpbGwgaGFuZGxlIHRoZSBhdG9taWMgcmVwbGFjZW1lbnQuXG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0RmlsZUFuZFByb2Nlc3MoZWRpdG9yLCB0aGlzLnVwbG9hZEFuZFJlcGxhY2VJbWFnZS5iaW5kKHRoaXMpLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKiBJbnRlcm5hbCBoZWxwZXIgdXNlZCBieSByZXBsYWNlbWVudCBsb2dpYyAqL1xuICBhc3luYyB1cGxvYWRBbmRSZXBsYWNlSW1hZ2UoXG4gICAgZWRpdG9yOiBFZGl0b3IsXG4gICAgZmlsZTogRmlsZSxcbiAgICBvcHRpb25zPzogQXRlSW1hZ2VVcGxvYWRPcHRpb25zXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIFN0b3JlIGN1cnJlbnQgcG9zaXRpb24gdG8gZW5zdXJlIHdlIGNhbiByZS1zZWxlY3QgdGhlIGltYWdlIGV2ZW4gaWYgc2VsZWN0aW9uIGJsdXJzIGR1cmluZyB1cGxvYWRcbiAgICBjb25zdCBwb3MgPSBlZGl0b3Iuc3RhdGUuc2VsZWN0aW9uLmZyb207XG4gICAgY29uc3Qgd2FzQWN0aXZlID0gZWRpdG9yLmlzQWN0aXZlKFwicmVzaXphYmxlSW1hZ2VcIik7XG5cbiAgICBhd2FpdCB0aGlzLnVwbG9hZEltYWdlV2l0aFByb2dyZXNzKFxuICAgICAgZWRpdG9yLFxuICAgICAgZmlsZSxcbiAgICAgIChlZCwgcmVzdWx0KSA9PiB7XG4gICAgICAgIGNvbnN0IGltYWdlRGF0YSA9IHtcbiAgICAgICAgICBzcmM6IHJlc3VsdC5zcmMsXG4gICAgICAgICAgYWx0OiByZXN1bHQubmFtZSxcbiAgICAgICAgICB0aXRsZTogYCR7cmVzdWx0Lm5hbWV9ICgke3Jlc3VsdC53aWR0aH3DlyR7cmVzdWx0LmhlaWdodH0pYCxcbiAgICAgICAgICB3aWR0aDogcmVzdWx0LndpZHRoLFxuICAgICAgICAgIGhlaWdodDogcmVzdWx0LmhlaWdodCxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBJZiB0aGUgaW1hZ2Ugd2FzIGFjdGl2ZSBvciBpcyBzdGlsbCBhY3RpdmUsIHVwZGF0ZSBpdCBhdG9taWNhbGx5XG4gICAgICAgIGlmICh3YXNBY3RpdmUgfHwgZWQuaXNBY3RpdmUoXCJyZXNpemFibGVJbWFnZVwiKSkge1xuICAgICAgICAgIGVkLmNoYWluKClcbiAgICAgICAgICAgIC5mb2N1cygpXG4gICAgICAgICAgICAudXBkYXRlQXR0cmlidXRlcyhcInJlc2l6YWJsZUltYWdlXCIsIGltYWdlRGF0YSlcbiAgICAgICAgICAgIC5zZXROb2RlU2VsZWN0aW9uKHBvcylcbiAgICAgICAgICAgIC5ydW4oKTtcbiAgICAgICAgICB0aGlzLnVwZGF0ZVNlbGVjdGVkSW1hZ2UoaW1hZ2VEYXRhKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBPdGhlcndpc2UgcmVwbGFjZSB3aGF0ZXZlciBpcyBzZWxlY3RlZCAob3IgaW5zZXJ0IGF0IGN1cnNvcilcbiAgICAgICAgICB0aGlzLmluc2VydEltYWdlKGVkLCBpbWFnZURhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWZ0ZXIgcmVwbGFjZW1lbnQsIGVuc3VyZSB0aGUgaW1hZ2UgaXMgdHJhY2tlZCBpbiBvdXIgc2lnbmFsc1xuICAgICAgICB0aGlzLnNlbGVjdEltYWdlKGVkKTtcbiAgICAgIH0sXG4gICAgICB0aGlzLnQoKS5yZXBsYWNpbmdJbWFnZSxcbiAgICAgIG9wdGlvbnNcbiAgICApO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,97 @@
|
|
|
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 || target?.closest("button") || target;
|
|
64
|
+
}
|
|
65
|
+
// Open the edit menu
|
|
66
|
+
this.open(trigger);
|
|
67
|
+
}
|
|
68
|
+
// ============================================
|
|
69
|
+
// Link Commands
|
|
70
|
+
// ============================================
|
|
71
|
+
/**
|
|
72
|
+
* Apply a link to the current selection.
|
|
73
|
+
*/
|
|
74
|
+
setLink(editor, url) {
|
|
75
|
+
if (!editor) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
|
|
79
|
+
this.close();
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Remove link from the current selection.
|
|
83
|
+
*/
|
|
84
|
+
unsetLink(editor) {
|
|
85
|
+
if (!editor) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
editor.chain().focus().extendMarkRange("link").unsetLink().run();
|
|
89
|
+
this.close();
|
|
90
|
+
}
|
|
91
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteLinkService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
92
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteLinkService }); }
|
|
93
|
+
}
|
|
94
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteLinkService, decorators: [{
|
|
95
|
+
type: Injectable
|
|
96
|
+
}] });
|
|
97
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRlLWxpbmsuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItdGlwdGFwLWVkaXRvci9zcmMvbGliL3NlcnZpY2VzL2F0ZS1saW5rLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7O0FBSW5ELE1BQU0sT0FBTyxjQUFjO0lBRDNCO1FBRUUsK0NBQStDO1FBQy9DLHdDQUF3QztRQUN4QywrQ0FBK0M7UUFFL0MsdUNBQXVDO1FBQzlCLGFBQVEsR0FBRyxNQUFNLENBQVUsS0FBSyxDQUFDLENBQUM7UUFFM0MsdUVBQXVFO1FBQzlELGdCQUFXLEdBQUcsTUFBTSxDQUFxQixJQUFJLENBQUMsQ0FBQztRQUV4RCwrRUFBK0U7UUFDdEUsa0JBQWEsR0FBRyxNQUFNLENBQVUsS0FBSyxDQUFDLENBQUM7S0F5RmpEO0lBdkZDLCtDQUErQztJQUMvQyx5QkFBeUI7SUFDekIsK0NBQStDO0lBRS9DOztPQUVHO0lBQ0gsSUFBSSxDQUFDLE9BQXFCO1FBQ3hCLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsQ0FBQztRQUN0QyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLO1FBQ0gsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSTtRQUNGLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdCLENBQUM7SUFFRDs7T0FFRztJQUNILGNBQWMsQ0FBQyxLQUFjO1FBQzNCLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsTUFBTSxDQUFDLE1BQWMsRUFBRSxVQUEyQjtRQUNoRCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixPQUFPO1FBQ1QsQ0FBQztRQUVELHNEQUFzRDtRQUN0RCxJQUFJLFVBQVUsSUFBSSxPQUFPLFVBQVUsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUNqRCxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQztZQUNqQyxPQUFPO1FBQ1QsQ0FBQztRQUVELHVEQUF1RDtRQUN2RCxJQUFJLE9BQWdDLENBQUM7UUFDckMsSUFBSSxVQUFVLElBQUksT0FBTyxVQUFVLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDakQsTUFBTSxNQUFNLEdBQUksVUFBb0IsQ0FBQyxNQUFxQixDQUFDO1lBQzNELE9BQU87Z0JBQ0gsVUFBb0IsQ0FBQyxhQUE2QixJQUFJLE1BQU0sRUFBRSxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksTUFBTSxDQUFDO1FBQ2hHLENBQUM7UUFFRCxxQkFBcUI7UUFDckIsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNyQixDQUFDO0lBRUQsK0NBQStDO0lBQy9DLGdCQUFnQjtJQUNoQiwrQ0FBK0M7SUFFL0M7O09BRUc7SUFDSCxPQUFPLENBQUMsTUFBYyxFQUFFLEdBQVc7UUFDakMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ1osT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQzVFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNmLENBQUM7SUFFRDs7T0FFRztJQUNILFNBQVMsQ0FBQyxNQUFjO1FBQ3RCLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNaLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNqRSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDZixDQUFDOytHQXBHVSxjQUFjO21IQUFkLGNBQWM7OzRGQUFkLGNBQWM7a0JBRDFCLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBzaWduYWwgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBFZGl0b3IgfSBmcm9tIFwiQHRpcHRhcC9jb3JlXCI7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBBdGVMaW5rU2VydmljZSB7XG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFN0YXRlIFNpZ25hbHMgKG93bmVkIGJ5IHRoaXMgc2VydmljZSlcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKiogV2hldGhlciBsaW5rIGVkaXQgbW9kZSBpcyBhY3RpdmUgKi9cbiAgcmVhZG9ubHkgZWRpdE1vZGUgPSBzaWduYWw8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gIC8qKiBSZWZlcmVuY2UgdG8gdGhlIGVsZW1lbnQgdGhhdCB0cmlnZ2VyZWQgdGhlIG1lbnUgKGZvciBhbmNob3JpbmcpICovXG4gIHJlYWRvbmx5IG1lbnVUcmlnZ2VyID0gc2lnbmFsPEhUTUxFbGVtZW50IHwgbnVsbD4obnVsbCk7XG5cbiAgLyoqIFdoZXRoZXIgdGhlIHVzZXIgaXMgY3VycmVudGx5IGludGVyYWN0aW5nIHdpdGggdGhlIGxpbmsgVUkgKGlucHV0IGZvY3VzKSAqL1xuICByZWFkb25seSBpc0ludGVyYWN0aW5nID0gc2lnbmFsPGJvb2xlYW4+KGZhbHNlKTtcblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBNZW51IExpZmVjeWNsZSBNZXRob2RzXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIE9wZW4gdGhlIGxpbmsgZWRpdCBtZW51LlxuICAgKi9cbiAgb3Blbih0cmlnZ2VyPzogSFRNTEVsZW1lbnQpOiB2b2lkIHtcbiAgICB0aGlzLm1lbnVUcmlnZ2VyLnNldCh0cmlnZ2VyIHx8IG51bGwpO1xuICAgIHRoaXMuZWRpdE1vZGUuc2V0KHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlIHRoZSBsaW5rIGVkaXQgbWVudS5cbiAgICovXG4gIGNsb3NlKCk6IHZvaWQge1xuICAgIHRoaXMuZWRpdE1vZGUuc2V0KGZhbHNlKTtcbiAgICB0aGlzLmlzSW50ZXJhY3Rpbmcuc2V0KGZhbHNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5hbCBjbGVhbnVwIChjYWxsZWQgYWZ0ZXIgVUkgaXMgaGlkZGVuKVxuICAgKi9cbiAgZG9uZSgpOiB2b2lkIHtcbiAgICB0aGlzLm1lbnVUcmlnZ2VyLnNldChudWxsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgaW50ZXJhY3Rpb24gc3RhdGVcbiAgICovXG4gIHNldEludGVyYWN0aW5nKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5pc0ludGVyYWN0aW5nLnNldCh2YWx1ZSk7XG4gIH1cblxuICAvKipcbiAgICogVG9nZ2xlIGxpbmsgbW9kZSBmcm9tIFVJLlxuICAgKiBJZiBhIFVSTCBzdHJpbmcgaXMgcHJvdmlkZWQsIGFwcGxpZXMgdGhlIGxpbmsgYW5kIGNsb3Nlcy5cbiAgICogSWYgYW4gRXZlbnQgaXMgcHJvdmlkZWQsIGV4dHJhY3RzIHRoZSB0cmlnZ2VyIGZvciBhbmNob3JpbmcuXG4gICAqL1xuICB0b2dnbGUoZWRpdG9yOiBFZGl0b3IsIHVybE9yRXZlbnQ/OiBzdHJpbmcgfCBFdmVudCk6IHZvaWQge1xuICAgIGlmICghZWRpdG9yKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gSWYgYSBzdHJpbmcgVVJMIGlzIHByb3ZpZGVkLCBzZXQgdGhlIGxpbmsgYW5kIGNsb3NlXG4gICAgaWYgKHVybE9yRXZlbnQgJiYgdHlwZW9mIHVybE9yRXZlbnQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIHRoaXMuc2V0TGluayhlZGl0b3IsIHVybE9yRXZlbnQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIElmIGFuIEV2ZW50IGlzIHByb3ZpZGVkLCBleHRyYWN0IHRoZSB0cmlnZ2VyIGVsZW1lbnRcbiAgICBsZXQgdHJpZ2dlcjogSFRNTEVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgaWYgKHVybE9yRXZlbnQgJiYgdHlwZW9mIHVybE9yRXZlbnQgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgIGNvbnN0IHRhcmdldCA9ICh1cmxPckV2ZW50IGFzIEV2ZW50KS50YXJnZXQgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICB0cmlnZ2VyID1cbiAgICAgICAgKCh1cmxPckV2ZW50IGFzIEV2ZW50KS5jdXJyZW50VGFyZ2V0IGFzIEhUTUxFbGVtZW50KSB8fCB0YXJnZXQ/LmNsb3Nlc3QoXCJidXR0b25cIikgfHwgdGFyZ2V0O1xuICAgIH1cblxuICAgIC8vIE9wZW4gdGhlIGVkaXQgbWVudVxuICAgIHRoaXMub3Blbih0cmlnZ2VyKTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIExpbmsgQ29tbWFuZHNcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogQXBwbHkgYSBsaW5rIHRvIHRoZSBjdXJyZW50IHNlbGVjdGlvbi5cbiAgICovXG4gIHNldExpbmsoZWRpdG9yOiBFZGl0b3IsIHVybDogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCFlZGl0b3IpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZWRpdG9yLmNoYWluKCkuZm9jdXMoKS5leHRlbmRNYXJrUmFuZ2UoXCJsaW5rXCIpLnNldExpbmsoeyBocmVmOiB1cmwgfSkucnVuKCk7XG4gICAgdGhpcy5jbG9zZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZSBsaW5rIGZyb20gdGhlIGN1cnJlbnQgc2VsZWN0aW9uLlxuICAgKi9cbiAgdW5zZXRMaW5rKGVkaXRvcjogRWRpdG9yKTogdm9pZCB7XG4gICAgaWYgKCFlZGl0b3IpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZWRpdG9yLmNoYWluKCkuZm9jdXMoKS5leHRlbmRNYXJrUmFuZ2UoXCJsaW5rXCIpLnVuc2V0TGluaygpLnJ1bigpO1xuICAgIHRoaXMuY2xvc2UoKTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes color values (rgb/rgba to hex).
|
|
3
|
+
*/
|
|
4
|
+
export function normalizeColor(color) {
|
|
5
|
+
if (!color || color === "transparent" || color === "rgba(0, 0, 0, 0)") {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
if (color.startsWith("#")) {
|
|
9
|
+
return color;
|
|
10
|
+
}
|
|
11
|
+
// Support both comma-separated (legacy) and space-separated (modern) rgb/rgba
|
|
12
|
+
const rgbMatch = color
|
|
13
|
+
.trim()
|
|
14
|
+
.match(/^rgba?\(\s*([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)(?:[,\s/]+([\d.]+))?\s*\)$/i);
|
|
15
|
+
// If it's a named color or something else we don't recognize,
|
|
16
|
+
// we can't easily normalize it to hex without a heavy dictionary.
|
|
17
|
+
// However, getComputedStyle usually returns rgb() which we handle above.
|
|
18
|
+
if (!rgbMatch) {
|
|
19
|
+
// Simple fallback for common named colors if getComputedStyle fails to return rgb
|
|
20
|
+
const named = { black: "#000000", white: "#ffffff", red: "#ff0000" };
|
|
21
|
+
if (named[color.toLowerCase()]) {
|
|
22
|
+
return named[color.toLowerCase()];
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const r = Math.max(0, Math.min(255, Math.round(parseFloat(rgbMatch[1]))));
|
|
27
|
+
const g = Math.max(0, Math.min(255, Math.round(parseFloat(rgbMatch[2]))));
|
|
28
|
+
const b = Math.max(0, Math.min(255, Math.round(parseFloat(rgbMatch[3]))));
|
|
29
|
+
const a = rgbMatch[4] ? parseFloat(rgbMatch[4]) : 1;
|
|
30
|
+
// If completely transparent, return null
|
|
31
|
+
if (a === 0) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return ("#" +
|
|
35
|
+
[r, g, b]
|
|
36
|
+
.map(n => n.toString(16).padStart(2, "0"))
|
|
37
|
+
.join("")
|
|
38
|
+
.toLowerCase());
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Calculate luminance (0-255).
|
|
42
|
+
*/
|
|
43
|
+
export function getLuminance(color) {
|
|
44
|
+
const normalized = normalizeColor(color);
|
|
45
|
+
if (!normalized) {
|
|
46
|
+
return 0;
|
|
47
|
+
} // Default to dark (luminance 0) if no color
|
|
48
|
+
const hex = normalized.replace("#", "");
|
|
49
|
+
const r = parseInt(hex.substring(0, 2), 16);
|
|
50
|
+
const g = parseInt(hex.substring(2, 4), 16);
|
|
51
|
+
const b = parseInt(hex.substring(4, 6), 16);
|
|
52
|
+
return (r * 299 + g * 587 + b * 114) / 1000;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Returns contrast color for readability.
|
|
56
|
+
*/
|
|
57
|
+
export function getContrastColor(color) {
|
|
58
|
+
return getLuminance(color) > 128 ? "black" : "white";
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRlLWNvbG9yLnV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci10aXB0YXAtZWRpdG9yL3NyYy9saWIvdXRpbHMvYXRlLWNvbG9yLnV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FBQyxLQUFnQztJQUM3RCxJQUFJLENBQUMsS0FBSyxJQUFJLEtBQUssS0FBSyxhQUFhLElBQUksS0FBSyxLQUFLLGtCQUFrQixFQUFFLENBQUM7UUFDdEUsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQ0QsSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDMUIsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsOEVBQThFO0lBQzlFLE1BQU0sUUFBUSxHQUFHLEtBQUs7U0FDbkIsSUFBSSxFQUFFO1NBQ04sS0FBSyxDQUFDLDRFQUE0RSxDQUFDLENBQUM7SUFFdkYsOERBQThEO0lBQzlELGtFQUFrRTtJQUNsRSx5RUFBeUU7SUFDekUsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2Qsa0ZBQWtGO1FBQ2xGLE1BQU0sS0FBSyxHQUEyQixFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLENBQUM7UUFDN0YsSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUMvQixPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUUsQ0FBQztRQUNyQyxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0UsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0UsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0UsTUFBTSxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVwRCx5Q0FBeUM7SUFDekMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDWixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxPQUFPLENBQ0wsR0FBRztRQUNILENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDTixHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7YUFDekMsSUFBSSxDQUFDLEVBQUUsQ0FBQzthQUNSLFdBQVcsRUFBRSxDQUNqQixDQUFDO0FBQ0osQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLFlBQVksQ0FBQyxLQUFnQztJQUMzRCxNQUFNLFVBQVUsR0FBRyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDekMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ2hCLE9BQU8sQ0FBQyxDQUFDO0lBQ1gsQ0FBQyxDQUFDLDRDQUE0QztJQUM5QyxNQUFNLEdBQUcsR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN4QyxNQUFNLENBQUMsR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDNUMsTUFBTSxDQUFDLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzVDLE1BQU0sQ0FBQyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUM1QyxPQUFPLENBQUMsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUM7QUFDOUMsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLEtBQWE7SUFDNUMsT0FBTyxZQUFZLENBQUMsS0FBSyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztBQUN2RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBOb3JtYWxpemVzIGNvbG9yIHZhbHVlcyAocmdiL3JnYmEgdG8gaGV4KS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5vcm1hbGl6ZUNvbG9yKGNvbG9yOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmICghY29sb3IgfHwgY29sb3IgPT09IFwidHJhbnNwYXJlbnRcIiB8fCBjb2xvciA9PT0gXCJyZ2JhKDAsIDAsIDAsIDApXCIpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBpZiAoY29sb3Iuc3RhcnRzV2l0aChcIiNcIikpIHtcbiAgICByZXR1cm4gY29sb3I7XG4gIH1cblxuICAvLyBTdXBwb3J0IGJvdGggY29tbWEtc2VwYXJhdGVkIChsZWdhY3kpIGFuZCBzcGFjZS1zZXBhcmF0ZWQgKG1vZGVybikgcmdiL3JnYmFcbiAgY29uc3QgcmdiTWF0Y2ggPSBjb2xvclxuICAgIC50cmltKClcbiAgICAubWF0Y2goL15yZ2JhP1xcKFxccyooW1xcZC5dKylbLFxcc10rKFtcXGQuXSspWyxcXHNdKyhbXFxkLl0rKSg/OlssXFxzL10rKFtcXGQuXSspKT9cXHMqXFwpJC9pKTtcblxuICAvLyBJZiBpdCdzIGEgbmFtZWQgY29sb3Igb3Igc29tZXRoaW5nIGVsc2Ugd2UgZG9uJ3QgcmVjb2duaXplLFxuICAvLyB3ZSBjYW4ndCBlYXNpbHkgbm9ybWFsaXplIGl0IHRvIGhleCB3aXRob3V0IGEgaGVhdnkgZGljdGlvbmFyeS5cbiAgLy8gSG93ZXZlciwgZ2V0Q29tcHV0ZWRTdHlsZSB1c3VhbGx5IHJldHVybnMgcmdiKCkgd2hpY2ggd2UgaGFuZGxlIGFib3ZlLlxuICBpZiAoIXJnYk1hdGNoKSB7XG4gICAgLy8gU2ltcGxlIGZhbGxiYWNrIGZvciBjb21tb24gbmFtZWQgY29sb3JzIGlmIGdldENvbXB1dGVkU3R5bGUgZmFpbHMgdG8gcmV0dXJuIHJnYlxuICAgIGNvbnN0IG5hbWVkOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0geyBibGFjazogXCIjMDAwMDAwXCIsIHdoaXRlOiBcIiNmZmZmZmZcIiwgcmVkOiBcIiNmZjAwMDBcIiB9O1xuICAgIGlmIChuYW1lZFtjb2xvci50b0xvd2VyQ2FzZSgpXSkge1xuICAgICAgcmV0dXJuIG5hbWVkW2NvbG9yLnRvTG93ZXJDYXNlKCldITtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCByID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMjU1LCBNYXRoLnJvdW5kKHBhcnNlRmxvYXQocmdiTWF0Y2hbMV0hKSkpKTtcbiAgY29uc3QgZyA9IE1hdGgubWF4KDAsIE1hdGgubWluKDI1NSwgTWF0aC5yb3VuZChwYXJzZUZsb2F0KHJnYk1hdGNoWzJdISkpKSk7XG4gIGNvbnN0IGIgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigyNTUsIE1hdGgucm91bmQocGFyc2VGbG9hdChyZ2JNYXRjaFszXSEpKSkpO1xuICBjb25zdCBhID0gcmdiTWF0Y2hbNF0gPyBwYXJzZUZsb2F0KHJnYk1hdGNoWzRdKSA6IDE7XG5cbiAgLy8gSWYgY29tcGxldGVseSB0cmFuc3BhcmVudCwgcmV0dXJuIG51bGxcbiAgaWYgKGEgPT09IDApIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgXCIjXCIgK1xuICAgIFtyLCBnLCBiXVxuICAgICAgLm1hcChuID0+IG4udG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDIsIFwiMFwiKSlcbiAgICAgIC5qb2luKFwiXCIpXG4gICAgICAudG9Mb3dlckNhc2UoKVxuICApO1xufVxuXG4vKipcbiAqIENhbGN1bGF0ZSBsdW1pbmFuY2UgKDAtMjU1KS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEx1bWluYW5jZShjb2xvcjogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IG51bWJlciB7XG4gIGNvbnN0IG5vcm1hbGl6ZWQgPSBub3JtYWxpemVDb2xvcihjb2xvcik7XG4gIGlmICghbm9ybWFsaXplZCkge1xuICAgIHJldHVybiAwO1xuICB9IC8vIERlZmF1bHQgdG8gZGFyayAobHVtaW5hbmNlIDApIGlmIG5vIGNvbG9yXG4gIGNvbnN0IGhleCA9IG5vcm1hbGl6ZWQucmVwbGFjZShcIiNcIiwgXCJcIik7XG4gIGNvbnN0IHIgPSBwYXJzZUludChoZXguc3Vic3RyaW5nKDAsIDIpLCAxNik7XG4gIGNvbnN0IGcgPSBwYXJzZUludChoZXguc3Vic3RyaW5nKDIsIDQpLCAxNik7XG4gIGNvbnN0IGIgPSBwYXJzZUludChoZXguc3Vic3RyaW5nKDQsIDYpLCAxNik7XG4gIHJldHVybiAociAqIDI5OSArIGcgKiA1ODcgKyBiICogMTE0KSAvIDEwMDA7XG59XG5cbi8qKlxuICogUmV0dXJucyBjb250cmFzdCBjb2xvciBmb3IgcmVhZGFiaWxpdHkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb250cmFzdENvbG9yKGNvbG9yOiBzdHJpbmcpOiBcImJsYWNrXCIgfCBcIndoaXRlXCIge1xuICByZXR1cm4gZ2V0THVtaW5hbmNlKGNvbG9yKSA+IDEyOCA/IFwiYmxhY2tcIiA6IFwid2hpdGVcIjtcbn1cbiJdfQ==
|