@syncfusion/ej2-richtexteditor 29.2.4-795127 → 29.2.4-803054

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/package.json CHANGED
@@ -80,6 +80,6 @@
80
80
  "url": "git+https://github.com/syncfusion/ej2-javascript-ui-controls.git"
81
81
  },
82
82
  "typings": "index.d.ts",
83
- "version": "29.2.4-795127",
83
+ "version": "29.2.4-803054",
84
84
  "sideEffects": false
85
85
  }
@@ -33,6 +33,10 @@ export declare class PasteCleanup {
33
33
  private destroy;
34
34
  private removeEventListener;
35
35
  private pasteClean;
36
+ private findSource;
37
+ private extractImageSrcDOM;
38
+ private fetchImageWithMetadata;
39
+ private getFilenameFromUrl;
36
40
  private splitBreakLine;
37
41
  private makeSpace;
38
42
  private imgUploading;
@@ -1,7 +1,7 @@
1
1
  import * as events from '../base/constant';
2
2
  import { Popup } from '@syncfusion/ej2-popups';
3
3
  import { RadioButton } from '@syncfusion/ej2-buttons';
4
- import { isNullOrUndefined as isNOU, isNullOrUndefined, detach, extend, addClass, removeClass } from '@syncfusion/ej2-base';
4
+ import { isNullOrUndefined as isNOU, isNullOrUndefined, detach, extend, addClass, removeClass, createElement } from '@syncfusion/ej2-base';
5
5
  import { getUniqueID, Browser, closest } from '@syncfusion/ej2-base';
6
6
  import { CLS_RTE_PASTE_KEEP_FORMAT, CLS_RTE_PASTE_REMOVE_FORMAT, CLS_RTE_PASTE_PLAIN_FORMAT } from '../base/classes';
7
7
  import { CLS_RTE_PASTE_OK, CLS_RTE_PASTE_CANCEL, CLS_RTE_DIALOG_MIN_HEIGHT } from '../base/classes';
@@ -13,6 +13,7 @@ import { Uploader } from '@syncfusion/ej2-inputs';
13
13
  import * as classes from '../base/classes';
14
14
  import { sanitizeHelper, convertToBlob } from '../base/util';
15
15
  import { scrollToCursor } from '../../common/util';
16
+ import { PASTE_SOURCE } from './../../editor-manager/base';
16
17
  /**
17
18
  * PasteCleanup module called when pasting content in RichTextEditor
18
19
  */
@@ -113,7 +114,11 @@ var PasteCleanup = /** @class */ (function () {
113
114
  if (e.args && value !== null && this.parent.editorMode === 'HTML') {
114
115
  var file = void 0;
115
116
  var files = e.args.clipboardData.files;
116
- if (value.length === 0 || (!isNOU(files) && files.length > 0)) {
117
+ var elm = createElement('p');
118
+ elm.innerHTML = value;
119
+ var source = this.findSource(elm);
120
+ var extractedSRC = this.parent.insertImageSettings.uploadRemoteURLs ? this.extractImageSrcDOM(value) : null;
121
+ if (value.length === 0 || (!isNOU(files) && files.length > 0 && source === 'html')) {
117
122
  var htmlRegex = new RegExp(/<\/[a-z][\s\S]*>/i);
118
123
  value = e.args.clipboardData.getData('text/plain');
119
124
  this.parent.trigger(events.beforePasteCleanup, { value: value });
@@ -156,6 +161,14 @@ var PasteCleanup = /** @class */ (function () {
156
161
  value = divElement.innerHTML;
157
162
  }
158
163
  }
164
+ else if (Array.isArray(extractedSRC) && extractedSRC.length &&
165
+ this.parent.insertImageSettings.saveUrl && this.parent.insertImageSettings.path) {
166
+ this.parent.trigger(events.beforePasteCleanup, { value: value });
167
+ for (var i = 0; i < extractedSRC.length; i++) {
168
+ var src = extractedSRC[i];
169
+ this.fetchImageWithMetadata(src);
170
+ }
171
+ }
159
172
  else if (value.length > 0) {
160
173
  this.parent.trigger(events.beforePasteCleanup, { value: value });
161
174
  this.parent.formatter.editorManager.observer.notify(EVENTS.MS_WORD_CLEANUP, {
@@ -212,6 +225,69 @@ var PasteCleanup = /** @class */ (function () {
212
225
  }
213
226
  }
214
227
  };
228
+ PasteCleanup.prototype.findSource = function (element) {
229
+ var metaNodes = element.querySelectorAll('meta');
230
+ for (var i = 0; i < metaNodes.length; i++) {
231
+ var metaNode = metaNodes[i];
232
+ var content = metaNode.getAttribute('content');
233
+ var name_1 = metaNode.getAttribute('name');
234
+ if (name_1 && name_1.toLowerCase().indexOf('generator') >= 0 && content && content.toLowerCase().indexOf('microsoft') >= 0) {
235
+ for (var j = 0; j < PASTE_SOURCE.length; j++) {
236
+ if (content.toLowerCase().indexOf(PASTE_SOURCE[j]) >= 0) {
237
+ return PASTE_SOURCE[j];
238
+ }
239
+ }
240
+ }
241
+ }
242
+ return 'html';
243
+ };
244
+ PasteCleanup.prototype.extractImageSrcDOM = function (value) {
245
+ if (!value || typeof value !== 'string') {
246
+ return null;
247
+ }
248
+ var parser = new DOMParser();
249
+ var doc = parser.parseFromString(value, 'text/html');
250
+ var images = doc.querySelectorAll('img');
251
+ if (images.length === 0) {
252
+ return null;
253
+ }
254
+ var srcs = Array.from(images)
255
+ .map(function (img) { return img.getAttribute('src') || img.src || ''; })
256
+ .map(function (src) { return src.trim(); })
257
+ .filter(function (src) { return !!src; })
258
+ // Exclude base64/data URLs, blob URLs, and anything containing "id="
259
+ .filter(function (src) {
260
+ var s = src.toLowerCase();
261
+ return !s.startsWith('data:') && !s.includes('base64') && !s.startsWith('blob:') && !s.includes('id=');
262
+ });
263
+ return srcs.length ? srcs : null;
264
+ };
265
+ PasteCleanup.prototype.fetchImageWithMetadata = function (url) {
266
+ var _this = this;
267
+ fetch(url)
268
+ .then(function (response) {
269
+ if (!response.ok) {
270
+ console.warn("Fetch status " + response.status + " for: " + url);
271
+ return null;
272
+ }
273
+ return response.blob();
274
+ })
275
+ .then(function (blob) {
276
+ if (blob) {
277
+ var filename = _this.getFilenameFromUrl(url) || 'downloaded-image.jpg';
278
+ var mimeType = blob.type || 'image/jpeg';
279
+ var file = new File([blob], filename, { type: mimeType });
280
+ var imageElement = _this.parent.inputElement.querySelector("img[src=\"" + url + "\"]");
281
+ _this.uploadMethod(file, imageElement);
282
+ }
283
+ });
284
+ };
285
+ // Helper method to extract filename from URL
286
+ PasteCleanup.prototype.getFilenameFromUrl = function (url) {
287
+ var pathname = new URL(url).pathname;
288
+ var filename = pathname.substring(pathname.lastIndexOf('/') + 1);
289
+ return filename || 'image.jpg';
290
+ };
215
291
  PasteCleanup.prototype.splitBreakLine = function (value) {
216
292
  var enterSplitText = value.split('\r\n\r\n');
217
293
  var finalText = '';
@@ -227,6 +227,13 @@ export interface ImageSettingsModel {
227
227
  */
228
228
  resizeByPercent?: boolean;
229
229
 
230
+ /**
231
+ * Specifies whether to allow uploading remote image URLs.
232
+ *
233
+ * @default false
234
+ */
235
+ uploadRemoteURLs?: boolean;
236
+
230
237
  }
231
238
 
232
239
  /**
@@ -201,6 +201,12 @@ export declare class ImageSettings extends ChildProperty<ImageSettings> {
201
201
  * @default false
202
202
  */
203
203
  resizeByPercent: boolean;
204
+ /**
205
+ * Specifies whether to allow uploading remote image URLs.
206
+ *
207
+ * @default false
208
+ */
209
+ uploadRemoteURLs: boolean;
204
210
  }
205
211
  /**
206
212
  * Configures the audio settings of the RichTextEditor.
@@ -155,6 +155,9 @@ var ImageSettings = /** @class */ (function (_super) {
155
155
  __decorate([
156
156
  Property(false)
157
157
  ], ImageSettings.prototype, "resizeByPercent", void 0);
158
+ __decorate([
159
+ Property(false)
160
+ ], ImageSettings.prototype, "uploadRemoteURLs", void 0);
158
161
  return ImageSettings;
159
162
  }(ChildProperty));
160
163
  export { ImageSettings };