@ckeditor/ckeditor5-media-embed 0.0.0-nightly-20241219.0 → 0.0.0-nightly-20241219.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.

Potentially problematic release.


This version of @ckeditor/ckeditor5-media-embed might be problematic. Click here for more details.

package/dist/index.js CHANGED
@@ -15,6 +15,8 @@ import { Undo } from '@ckeditor/ckeditor5-undo/dist/index.js';
15
15
  * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
16
16
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
17
17
  */ /**
18
+ * @module media-embed/converters
19
+ */ /**
18
20
  * Returns a function that converts the model "url" attribute to the view representation.
19
21
  *
20
22
  * Depending on the configuration, the view representation can be "semantic" (for the data pipeline):
@@ -157,8 +159,8 @@ import { Undo } from '@ckeditor/ckeditor5-undo/dist/index.js';
157
159
  * ```
158
160
  */ class MediaEmbedCommand extends Command {
159
161
  /**
160
- * @inheritDoc
161
- */ refresh() {
162
+ * @inheritDoc
163
+ */ refresh() {
162
164
  const model = this.editor.model;
163
165
  const selection = model.document.selection;
164
166
  const selectedMedia = getSelectedMediaModelWidget(selection);
@@ -166,14 +168,14 @@ import { Undo } from '@ckeditor/ckeditor5-undo/dist/index.js';
166
168
  this.isEnabled = isMediaSelected(selection) || isAllowedInParent(selection, model);
167
169
  }
168
170
  /**
169
- * Executes the command, which either:
170
- *
171
- * * updates the URL of the selected media,
172
- * * inserts the new media into the editor and puts the selection around it.
173
- *
174
- * @fires execute
175
- * @param url The URL of the media.
176
- */ execute(url) {
171
+ * Executes the command, which either:
172
+ *
173
+ * * updates the URL of the selected media,
174
+ * * inserts the new media into the editor and puts the selection around it.
175
+ *
176
+ * @fires execute
177
+ * @param url The URL of the media.
178
+ */ execute(url) {
177
179
  const model = this.editor.model;
178
180
  const selection = model.document.selection;
179
181
  const selectedMedia = getSelectedMediaModelWidget(selection);
@@ -215,11 +217,18 @@ const mediaPlaceholderIconViewBox = '0 0 64 42';
215
217
  * Mostly used by the {@link module:media-embed/mediaembedediting~MediaEmbedEditing} plugin.
216
218
  */ class MediaRegistry {
217
219
  /**
218
- * Creates an instance of the {@link module:media-embed/mediaregistry~MediaRegistry} class.
219
- *
220
- * @param locale The localization services instance.
221
- * @param config The configuration of the media embed feature.
222
- */ constructor(locale, config){
220
+ * The {@link module:utils/locale~Locale} instance.
221
+ */ locale;
222
+ /**
223
+ * The media provider definitions available for the registry. Usually corresponding with the
224
+ * {@link module:media-embed/mediaembedconfig~MediaEmbedConfig media configuration}.
225
+ */ providerDefinitions;
226
+ /**
227
+ * Creates an instance of the {@link module:media-embed/mediaregistry~MediaRegistry} class.
228
+ *
229
+ * @param locale The localization services instance.
230
+ * @param config The configuration of the media embed feature.
231
+ */ constructor(locale, config){
223
232
  const providers = config.providers;
224
233
  const extraProviders = config.extraProviders || [];
225
234
  const removedProviders = new Set(config.removeProviders);
@@ -227,12 +236,12 @@ const mediaPlaceholderIconViewBox = '0 0 64 42';
227
236
  const name = provider.name;
228
237
  if (!name) {
229
238
  /**
230
- * One of the providers (or extra providers) specified in the media embed configuration
231
- * has no name and will not be used by the editor. In order to get this media
232
- * provider working, double check your editor configuration.
233
- *
234
- * @error media-embed-no-provider-name
235
- */ logWarning('media-embed-no-provider-name', {
239
+ * One of the providers (or extra providers) specified in the media embed configuration
240
+ * has no name and will not be used by the editor. In order to get this media
241
+ * provider working, double check your editor configuration.
242
+ *
243
+ * @error media-embed-no-provider-name
244
+ */ logWarning('media-embed-no-provider-name', {
236
245
  provider
237
246
  });
238
247
  return false;
@@ -243,29 +252,29 @@ const mediaPlaceholderIconViewBox = '0 0 64 42';
243
252
  this.providerDefinitions = providerDefinitions;
244
253
  }
245
254
  /**
246
- * Checks whether the passed URL is representing a certain media type allowed in the editor.
247
- *
248
- * @param url The URL to be checked
249
- */ hasMedia(url) {
255
+ * Checks whether the passed URL is representing a certain media type allowed in the editor.
256
+ *
257
+ * @param url The URL to be checked
258
+ */ hasMedia(url) {
250
259
  return !!this._getMedia(url);
251
260
  }
252
261
  /**
253
- * For the given media URL string and options, it returns the {@link module:engine/view/element~Element view element}
254
- * representing that media.
255
- *
256
- * **Note:** If no URL is specified, an empty view element is returned.
257
- *
258
- * @param writer The view writer used to produce a view element.
259
- * @param url The URL to be translated into a view element.
260
- */ getMediaViewElement(writer, url, options) {
262
+ * For the given media URL string and options, it returns the {@link module:engine/view/element~Element view element}
263
+ * representing that media.
264
+ *
265
+ * **Note:** If no URL is specified, an empty view element is returned.
266
+ *
267
+ * @param writer The view writer used to produce a view element.
268
+ * @param url The URL to be translated into a view element.
269
+ */ getMediaViewElement(writer, url, options) {
261
270
  return this._getMedia(url).getViewElement(writer, options);
262
271
  }
263
272
  /**
264
- * Returns a `Media` instance for the given URL.
265
- *
266
- * @param url The URL of the media.
267
- * @returns The `Media` instance or `null` when there is none.
268
- */ _getMedia(url) {
273
+ * Returns a `Media` instance for the given URL.
274
+ *
275
+ * @param url The URL of the media.
276
+ * @returns The `Media` instance or `null` when there is none.
277
+ */ _getMedia(url) {
269
278
  if (!url) {
270
279
  return new Media(this.locale);
271
280
  }
@@ -283,11 +292,11 @@ const mediaPlaceholderIconViewBox = '0 0 64 42';
283
292
  return null;
284
293
  }
285
294
  /**
286
- * Tries to match `url` to `pattern`.
287
- *
288
- * @param url The URL of the media.
289
- * @param pattern The pattern that should accept the media URL.
290
- */ _getUrlMatches(url, pattern) {
295
+ * Tries to match `url` to `pattern`.
296
+ *
297
+ * @param url The URL of the media.
298
+ * @param pattern The pattern that should accept the media URL.
299
+ */ _getUrlMatches(url, pattern) {
291
300
  // 1. Try to match without stripping the protocol and "www" subdomain.
292
301
  let match = url.match(pattern);
293
302
  if (match) {
@@ -313,6 +322,20 @@ const mediaPlaceholderIconViewBox = '0 0 64 42';
313
322
  *
314
323
  * It can be rendered to the {@link module:engine/view/element~Element view element} and used in the editing or data pipeline.
315
324
  */ class Media {
325
+ /**
326
+ * The URL this Media instance represents.
327
+ */ url;
328
+ /**
329
+ * Shorthand for {@link module:utils/locale~Locale#t}.
330
+ *
331
+ * @see module:utils/locale~Locale#t
332
+ */ _locale;
333
+ /**
334
+ * The output of the `RegExp.match` which validated the {@link #url} of this media.
335
+ */ _match;
336
+ /**
337
+ * The function returning the HTML string preview of this media.
338
+ */ _previewRenderer;
316
339
  constructor(locale, url, match, previewRenderer){
317
340
  this.url = this._getValidUrl(url);
318
341
  this._locale = locale;
@@ -320,10 +343,10 @@ const mediaPlaceholderIconViewBox = '0 0 64 42';
320
343
  this._previewRenderer = previewRenderer;
321
344
  }
322
345
  /**
323
- * Returns the view element representation of the media.
324
- *
325
- * @param writer The view writer used to produce a view element.
326
- */ getViewElement(writer, options) {
346
+ * Returns the view element representation of the media.
347
+ *
348
+ * @param writer The view writer used to produce a view element.
349
+ */ getViewElement(writer, options) {
327
350
  const attributes = {};
328
351
  let viewElement;
329
352
  if (options.renderForEditingView || options.renderMediaPreview && this.url && this._previewRenderer) {
@@ -347,8 +370,8 @@ const mediaPlaceholderIconViewBox = '0 0 64 42';
347
370
  return viewElement;
348
371
  }
349
372
  /**
350
- * Returns the HTML string of the media content preview.
351
- */ _getPreviewHtml(options) {
373
+ * Returns the HTML string of the media content preview.
374
+ */ _getPreviewHtml(options) {
352
375
  if (this._previewRenderer) {
353
376
  return this._previewRenderer(this._match);
354
377
  } else {
@@ -361,8 +384,8 @@ const mediaPlaceholderIconViewBox = '0 0 64 42';
361
384
  }
362
385
  }
363
386
  /**
364
- * Returns the placeholder HTML when the media has no content preview.
365
- */ _getPlaceholderHtml() {
387
+ * Returns the placeholder HTML when the media has no content preview.
388
+ */ _getPlaceholderHtml() {
366
389
  const icon = new IconView();
367
390
  const t = this._locale.t;
368
391
  icon.content = mediaPlaceholderIcon;
@@ -408,10 +431,10 @@ const mediaPlaceholderIconViewBox = '0 0 64 42';
408
431
  return placeholder.outerHTML;
409
432
  }
410
433
  /**
411
- * Returns the full URL to the specified media.
412
- *
413
- * @param url The URL of the media.
414
- */ _getValidUrl(url) {
434
+ * Returns the full URL to the specified media.
435
+ *
436
+ * @param url The URL of the media.
437
+ */ _getValidUrl(url) {
415
438
  if (!url) {
416
439
  return null;
417
440
  }
@@ -426,18 +449,21 @@ const mediaPlaceholderIconViewBox = '0 0 64 42';
426
449
  * The media embed editing feature.
427
450
  */ class MediaEmbedEditing extends Plugin {
428
451
  /**
429
- * @inheritDoc
430
- */ static get pluginName() {
452
+ * @inheritDoc
453
+ */ static get pluginName() {
431
454
  return 'MediaEmbedEditing';
432
455
  }
433
456
  /**
434
- * @inheritDoc
435
- */ static get isOfficialPlugin() {
457
+ * @inheritDoc
458
+ */ static get isOfficialPlugin() {
436
459
  return true;
437
460
  }
438
461
  /**
439
- * @inheritDoc
440
- */ constructor(editor){
462
+ * The media registry managing the media providers in the editor.
463
+ */ registry;
464
+ /**
465
+ * @inheritDoc
466
+ */ constructor(editor){
441
467
  super(editor);
442
468
  editor.config.define('mediaEmbed', {
443
469
  elementName: 'oembed',
@@ -532,8 +558,8 @@ const mediaPlaceholderIconViewBox = '0 0 64 42';
532
558
  this.registry = new MediaRegistry(editor.locale, editor.config.get('mediaEmbed'));
533
559
  }
534
560
  /**
535
- * @inheritDoc
536
- */ init() {
561
+ * @inheritDoc
562
+ */ init() {
537
563
  const editor = this.editor;
538
564
  const schema = editor.model.schema;
539
565
  const t = editor.t;
@@ -649,8 +675,8 @@ const URL_REGEXP = /^(?:http(s)?:\/\/)?[\w-]+\.[\w-.~:/?#[\]@!$&'()*+,;=%]+$/;
649
675
  * them shortly after they are injected into the document.
650
676
  */ class AutoMediaEmbed extends Plugin {
651
677
  /**
652
- * @inheritDoc
653
- */ static get requires() {
678
+ * @inheritDoc
679
+ */ static get requires() {
654
680
  return [
655
681
  Clipboard,
656
682
  Delete,
@@ -658,25 +684,33 @@ const URL_REGEXP = /^(?:http(s)?:\/\/)?[\w-]+\.[\w-.~:/?#[\]@!$&'()*+,;=%]+$/;
658
684
  ];
659
685
  }
660
686
  /**
661
- * @inheritDoc
662
- */ static get pluginName() {
687
+ * @inheritDoc
688
+ */ static get pluginName() {
663
689
  return 'AutoMediaEmbed';
664
690
  }
665
691
  /**
666
- * @inheritDoc
667
- */ static get isOfficialPlugin() {
692
+ * @inheritDoc
693
+ */ static get isOfficialPlugin() {
668
694
  return true;
669
695
  }
670
696
  /**
671
- * @inheritDoc
672
- */ constructor(editor){
697
+ * The paste–to–embed `setTimeout` ID. Stored as a property to allow
698
+ * cleaning of the timeout.
699
+ */ _timeoutId;
700
+ /**
701
+ * The position where the `<media>` element will be inserted after the timeout,
702
+ * determined each time the new content is pasted into the document.
703
+ */ _positionToInsert;
704
+ /**
705
+ * @inheritDoc
706
+ */ constructor(editor){
673
707
  super(editor);
674
708
  this._timeoutId = null;
675
709
  this._positionToInsert = null;
676
710
  }
677
711
  /**
678
- * @inheritDoc
679
- */ init() {
712
+ * @inheritDoc
713
+ */ init() {
680
714
  const editor = this.editor;
681
715
  const modelDocument = editor.model.document;
682
716
  // We need to listen on `Clipboard#inputTransformation` because we need to save positions of selection.
@@ -710,12 +744,12 @@ const URL_REGEXP = /^(?:http(s)?:\/\/)?[\w-]+\.[\w-.~:/?#[\]@!$&'()*+,;=%]+$/;
710
744
  });
711
745
  }
712
746
  /**
713
- * Analyzes the part of the document between provided positions in search for a URL representing media.
714
- * When the URL is found, it is automatically converted into media.
715
- *
716
- * @param leftPosition Left position of the selection.
717
- * @param rightPosition Right position of the selection.
718
- */ _embedMediaBetweenPositions(leftPosition, rightPosition) {
747
+ * Analyzes the part of the document between provided positions in search for a URL representing media.
748
+ * When the URL is found, it is automatically converted into media.
749
+ *
750
+ * @param leftPosition Left position of the selection.
751
+ * @param rightPosition Right position of the selection.
752
+ */ _embedMediaBetweenPositions(leftPosition, rightPosition) {
719
753
  const editor = this.editor;
720
754
  const mediaRegistry = editor.plugins.get(MediaEmbedEditing).registry;
721
755
  // TODO: Use marker instead of LiveRange & LivePositions.
@@ -775,9 +809,28 @@ const URL_REGEXP = /^(?:http(s)?:\/\/)?[\w-]+\.[\w-.~:/?#[\]@!$&'()*+,;=%]+$/;
775
809
  * See {@link module:media-embed/ui/mediaformview~MediaFormView}.
776
810
  */ class MediaFormView extends View {
777
811
  /**
778
- * @param validators Form validators used by {@link #isValid}.
779
- * @param locale The localization services instance.
780
- */ constructor(validators, locale){
812
+ * Tracks information about the DOM focus in the form.
813
+ */ focusTracker;
814
+ /**
815
+ * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
816
+ */ keystrokes;
817
+ /**
818
+ * The URL input view.
819
+ */ urlInputView;
820
+ /**
821
+ * An array of form validators used by {@link #isValid}.
822
+ */ _validators;
823
+ /**
824
+ * The default info text for the {@link #urlInputView}.
825
+ */ _urlInputViewInfoDefault;
826
+ /**
827
+ * The info text with an additional tip for the {@link #urlInputView},
828
+ * displayed when the input has some value.
829
+ */ _urlInputViewInfoTip;
830
+ /**
831
+ * @param validators Form validators used by {@link #isValid}.
832
+ * @param locale The localization services instance.
833
+ */ constructor(validators, locale){
781
834
  super(locale);
782
835
  this.focusTracker = new FocusTracker();
783
836
  this.keystrokes = new KeystrokeHandler();
@@ -800,8 +853,8 @@ const URL_REGEXP = /^(?:http(s)?:\/\/)?[\w-]+\.[\w-.~:/?#[\]@!$&'()*+,;=%]+$/;
800
853
  });
801
854
  }
802
855
  /**
803
- * @inheritDoc
804
- */ render() {
856
+ * @inheritDoc
857
+ */ render() {
805
858
  super.render();
806
859
  submitHandler({
807
860
  view: this
@@ -812,31 +865,31 @@ const URL_REGEXP = /^(?:http(s)?:\/\/)?[\w-]+\.[\w-.~:/?#[\]@!$&'()*+,;=%]+$/;
812
865
  this.keystrokes.listenTo(this.element);
813
866
  }
814
867
  /**
815
- * @inheritDoc
816
- */ destroy() {
868
+ * @inheritDoc
869
+ */ destroy() {
817
870
  super.destroy();
818
871
  this.focusTracker.destroy();
819
872
  this.keystrokes.destroy();
820
873
  }
821
874
  /**
822
- * Focuses the {@link #urlInputView}.
823
- */ focus() {
875
+ * Focuses the {@link #urlInputView}.
876
+ */ focus() {
824
877
  this.urlInputView.focus();
825
878
  }
826
879
  /**
827
- * The native DOM `value` of the {@link #urlInputView} element.
828
- *
829
- * **Note**: Do not confuse it with the {@link module:ui/inputtext/inputtextview~InputTextView#value}
830
- * which works one way only and may not represent the actual state of the component in the DOM.
831
- */ get url() {
880
+ * The native DOM `value` of the {@link #urlInputView} element.
881
+ *
882
+ * **Note**: Do not confuse it with the {@link module:ui/inputtext/inputtextview~InputTextView#value}
883
+ * which works one way only and may not represent the actual state of the component in the DOM.
884
+ */ get url() {
832
885
  return this.urlInputView.fieldView.element.value.trim();
833
886
  }
834
887
  set url(url) {
835
888
  this.urlInputView.fieldView.value = url.trim();
836
889
  }
837
890
  /**
838
- * Validates the form and returns `false` when some fields are invalid.
839
- */ isValid() {
891
+ * Validates the form and returns `false` when some fields are invalid.
892
+ */ isValid() {
840
893
  this.resetFormStatus();
841
894
  for (const validator of this._validators){
842
895
  const errorText = validator(this);
@@ -850,19 +903,19 @@ const URL_REGEXP = /^(?:http(s)?:\/\/)?[\w-]+\.[\w-.~:/?#[\]@!$&'()*+,;=%]+$/;
850
903
  return true;
851
904
  }
852
905
  /**
853
- * Cleans up the supplementary error and information text of the {@link #urlInputView}
854
- * bringing them back to the state when the form has been displayed for the first time.
855
- *
856
- * See {@link #isValid}.
857
- */ resetFormStatus() {
906
+ * Cleans up the supplementary error and information text of the {@link #urlInputView}
907
+ * bringing them back to the state when the form has been displayed for the first time.
908
+ *
909
+ * See {@link #isValid}.
910
+ */ resetFormStatus() {
858
911
  this.urlInputView.errorText = null;
859
912
  this.urlInputView.infoText = this._urlInputViewInfoDefault;
860
913
  }
861
914
  /**
862
- * Creates a labeled input view.
863
- *
864
- * @returns Labeled input view instance.
865
- */ _createUrlInput() {
915
+ * Creates a labeled input view.
916
+ *
917
+ * @returns Labeled input view instance.
918
+ */ _createUrlInput() {
866
919
  const t = this.locale.t;
867
920
  const labeledInput = new LabeledFieldView(this.locale, createLabeledInputText);
868
921
  const inputField = labeledInput.fieldView;
@@ -886,26 +939,27 @@ var mediaIcon = "<svg viewBox=\"0 0 22 20\" xmlns=\"http://www.w3.org/2000/svg\"
886
939
  * The media embed UI plugin.
887
940
  */ class MediaEmbedUI extends Plugin {
888
941
  /**
889
- * @inheritDoc
890
- */ static get requires() {
942
+ * @inheritDoc
943
+ */ static get requires() {
891
944
  return [
892
945
  MediaEmbedEditing,
893
946
  Dialog
894
947
  ];
895
948
  }
896
949
  /**
897
- * @inheritDoc
898
- */ static get pluginName() {
950
+ * @inheritDoc
951
+ */ static get pluginName() {
899
952
  return 'MediaEmbedUI';
900
953
  }
901
954
  /**
902
- * @inheritDoc
903
- */ static get isOfficialPlugin() {
955
+ * @inheritDoc
956
+ */ static get isOfficialPlugin() {
904
957
  return true;
905
958
  }
959
+ _formView;
906
960
  /**
907
- * @inheritDoc
908
- */ init() {
961
+ * @inheritDoc
962
+ */ init() {
909
963
  const editor = this.editor;
910
964
  editor.ui.componentFactory.add('mediaEmbed', ()=>{
911
965
  const t = this.editor.locale.t;
@@ -922,8 +976,8 @@ var mediaIcon = "<svg viewBox=\"0 0 22 20\" xmlns=\"http://www.w3.org/2000/svg\"
922
976
  });
923
977
  }
924
978
  /**
925
- * Creates a button for menu bar that will show media embed dialog.
926
- */ _createDialogButton(ButtonClass) {
979
+ * Creates a button for menu bar that will show media embed dialog.
980
+ */ _createDialogButton(ButtonClass) {
927
981
  const editor = this.editor;
928
982
  const buttonView = new ButtonClass(editor.locale);
929
983
  const command = editor.commands.get('mediaEmbed');
@@ -1011,8 +1065,8 @@ function getFormValidators(t, registry) {
1011
1065
  * * The {@link module:media-embed/automediaembed~AutoMediaEmbed auto-media embed feature}.
1012
1066
  */ class MediaEmbed extends Plugin {
1013
1067
  /**
1014
- * @inheritDoc
1015
- */ static get requires() {
1068
+ * @inheritDoc
1069
+ */ static get requires() {
1016
1070
  return [
1017
1071
  MediaEmbedEditing,
1018
1072
  MediaEmbedUI,
@@ -1021,13 +1075,13 @@ function getFormValidators(t, registry) {
1021
1075
  ];
1022
1076
  }
1023
1077
  /**
1024
- * @inheritDoc
1025
- */ static get pluginName() {
1078
+ * @inheritDoc
1079
+ */ static get pluginName() {
1026
1080
  return 'MediaEmbed';
1027
1081
  }
1028
1082
  /**
1029
- * @inheritDoc
1030
- */ static get isOfficialPlugin() {
1083
+ * @inheritDoc
1084
+ */ static get isOfficialPlugin() {
1031
1085
  return true;
1032
1086
  }
1033
1087
  }
@@ -1039,25 +1093,25 @@ function getFormValidators(t, registry) {
1039
1093
  * {@link module:media-embed/mediaembedconfig~MediaEmbedConfig#toolbar `media.toolbar` configuration option}.
1040
1094
  */ class MediaEmbedToolbar extends Plugin {
1041
1095
  /**
1042
- * @inheritDoc
1043
- */ static get requires() {
1096
+ * @inheritDoc
1097
+ */ static get requires() {
1044
1098
  return [
1045
1099
  WidgetToolbarRepository
1046
1100
  ];
1047
1101
  }
1048
1102
  /**
1049
- * @inheritDoc
1050
- */ static get pluginName() {
1103
+ * @inheritDoc
1104
+ */ static get pluginName() {
1051
1105
  return 'MediaEmbedToolbar';
1052
1106
  }
1053
1107
  /**
1054
- * @inheritDoc
1055
- */ static get isOfficialPlugin() {
1108
+ * @inheritDoc
1109
+ */ static get isOfficialPlugin() {
1056
1110
  return true;
1057
1111
  }
1058
1112
  /**
1059
- * @inheritDoc
1060
- */ afterInit() {
1113
+ * @inheritDoc
1114
+ */ afterInit() {
1061
1115
  const editor = this.editor;
1062
1116
  const t = editor.t;
1063
1117
  const widgetToolbarRepository = editor.plugins.get(WidgetToolbarRepository);