@ckeditor/ckeditor5-link 0.0.0-nightly-20240509.0 → 0.0.0-nightly-20240511.0

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/dist/index.js CHANGED
@@ -5,24 +5,31 @@
5
5
  import { Command, Plugin, icons } from '@ckeditor/ckeditor5-core/dist/index.js';
6
6
  import { findAttributeRange, TwoStepCaretMovement, Input, inlineHighlight, Delete, TextWatcher, getLastTextLine } from '@ckeditor/ckeditor5-typing/dist/index.js';
7
7
  import { ClipboardPipeline } from '@ckeditor/ckeditor5-clipboard/dist/index.js';
8
- import { toMap, first, Collection, ObservableMixin, env, keyCodes, FocusTracker, KeystrokeHandler } from '@ckeditor/ckeditor5-utils/dist/index.js';
8
+ import { toMap, Collection, first, ObservableMixin, env, keyCodes, FocusTracker, KeystrokeHandler } from '@ckeditor/ckeditor5-utils/dist/index.js';
9
9
  import { upperFirst } from 'lodash-es';
10
10
  import { ClickObserver, Matcher } from '@ckeditor/ckeditor5-engine/dist/index.js';
11
- import { View, submitHandler, LabeledFieldView, createLabeledInputText, ButtonView, SwitchButtonView, ViewCollection, FocusCycler, ContextualBalloon, CssTransitionDisablerMixin, MenuBarMenuListItemButtonView, clickOutsideHandler } from '@ckeditor/ckeditor5-ui/dist/index.js';
11
+ import { View, ViewCollection, FocusCycler, submitHandler, LabeledFieldView, createLabeledInputText, ButtonView, SwitchButtonView, ContextualBalloon, CssTransitionDisablerMixin, MenuBarMenuListItemButtonView, clickOutsideHandler } from '@ckeditor/ckeditor5-ui/dist/index.js';
12
12
  import { isWidget } from '@ckeditor/ckeditor5-widget/dist/index.js';
13
13
 
14
- class AutomaticDecorators {
14
+ /**
15
+ * Helper class that ties together all {@link module:link/linkconfig~LinkDecoratorAutomaticDefinition} and provides
16
+ * the {@link module:engine/conversion/downcasthelpers~DowncastHelpers#attributeToElement downcast dispatchers} for them.
17
+ */ class AutomaticDecorators {
18
+ /**
19
+ * Stores the definition of {@link module:link/linkconfig~LinkDecoratorAutomaticDefinition automatic decorators}.
20
+ * This data is used as a source for a downcast dispatcher to create a proper conversion to output data.
21
+ */ _definitions = new Set();
15
22
  /**
16
- * Gives information about the number of decorators stored in the {@link module:link/utils/automaticdecorators~AutomaticDecorators}
17
- * instance.
18
- */ get length() {
23
+ * Gives information about the number of decorators stored in the {@link module:link/utils/automaticdecorators~AutomaticDecorators}
24
+ * instance.
25
+ */ get length() {
19
26
  return this._definitions.size;
20
27
  }
21
28
  /**
22
- * Adds automatic decorator objects or an array with them to be used during downcasting.
23
- *
24
- * @param item A configuration object of automatic rules for decorating links. It might also be an array of such objects.
25
- */ add(item) {
29
+ * Adds automatic decorator objects or an array with them to be used during downcasting.
30
+ *
31
+ * @param item A configuration object of automatic rules for decorating links. It might also be an array of such objects.
32
+ */ add(item) {
26
33
  if (Array.isArray(item)) {
27
34
  item.forEach((item)=>this._definitions.add(item));
28
35
  } else {
@@ -30,10 +37,10 @@ class AutomaticDecorators {
30
37
  }
31
38
  }
32
39
  /**
33
- * Provides the conversion helper used in the {@link module:engine/conversion/downcasthelpers~DowncastHelpers#add} method.
34
- *
35
- * @returns A dispatcher function used as conversion helper in {@link module:engine/conversion/downcasthelpers~DowncastHelpers#add}.
36
- */ getDispatcher() {
40
+ * Provides the conversion helper used in the {@link module:engine/conversion/downcasthelpers~DowncastHelpers#add} method.
41
+ *
42
+ * @returns A dispatcher function used as conversion helper in {@link module:engine/conversion/downcasthelpers~DowncastHelpers#add}.
43
+ */ getDispatcher() {
37
44
  return (dispatcher)=>{
38
45
  dispatcher.on('attribute:linkHref', (evt, data, conversionApi)=>{
39
46
  // There is only test as this behavior decorates links and
@@ -76,11 +83,11 @@ class AutomaticDecorators {
76
83
  };
77
84
  }
78
85
  /**
79
- * Provides the conversion helper used in the {@link module:engine/conversion/downcasthelpers~DowncastHelpers#add} method
80
- * when linking images.
81
- *
82
- * @returns A dispatcher function used as conversion helper in {@link module:engine/conversion/downcasthelpers~DowncastHelpers#add}.
83
- */ getDispatcherForLinkedImage() {
86
+ * Provides the conversion helper used in the {@link module:engine/conversion/downcasthelpers~DowncastHelpers#add} method
87
+ * when linking images.
88
+ *
89
+ * @returns A dispatcher function used as conversion helper in {@link module:engine/conversion/downcasthelpers~DowncastHelpers#add}.
90
+ */ getDispatcherForLinkedImage() {
84
91
  return (dispatcher)=>{
85
92
  dispatcher.on('attribute:linkHref:imageBlock', (evt, data, { writer, mapper })=>{
86
93
  const viewFigure = mapper.toViewElement(data.item);
@@ -122,12 +129,6 @@ class AutomaticDecorators {
122
129
  });
123
130
  };
124
131
  }
125
- constructor(){
126
- /**
127
- * Stores the definition of {@link module:link/linkconfig~LinkDecoratorAutomaticDefinition automatic decorators}.
128
- * This data is used as a source for a downcast dispatcher to create a proper conversion to output data.
129
- */ this._definitions = new Set();
130
- }
131
132
  }
132
133
 
133
134
  const ATTRIBUTE_WHITESPACES = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g; // eslint-disable-line no-control-regex
@@ -255,17 +256,29 @@ const DEFAULT_LINK_PROTOCOLS = [
255
256
  window.open(link, '_blank', 'noopener');
256
257
  }
257
258
 
258
- class LinkCommand extends Command {
259
+ /**
260
+ * The link command. It is used by the {@link module:link/link~Link link feature}.
261
+ */ class LinkCommand extends Command {
259
262
  /**
260
- * Synchronizes the state of {@link #manualDecorators} with the currently present elements in the model.
261
- */ restoreManualDecoratorStates() {
263
+ * A collection of {@link module:link/utils/manualdecorator~ManualDecorator manual decorators}
264
+ * corresponding to the {@link module:link/linkconfig~LinkConfig#decorators decorator configuration}.
265
+ *
266
+ * You can consider it a model with states of manual decorators added to the currently selected link.
267
+ */ manualDecorators = new Collection();
268
+ /**
269
+ * An instance of the helper that ties together all {@link module:link/linkconfig~LinkDecoratorAutomaticDefinition}
270
+ * that are used by the {@glink features/link link} and the {@glink features/images/images-linking linking images} features.
271
+ */ automaticDecorators = new AutomaticDecorators();
272
+ /**
273
+ * Synchronizes the state of {@link #manualDecorators} with the currently present elements in the model.
274
+ */ restoreManualDecoratorStates() {
262
275
  for (const manualDecorator of this.manualDecorators){
263
276
  manualDecorator.value = this._getDecoratorStateFromModel(manualDecorator.id);
264
277
  }
265
278
  }
266
279
  /**
267
- * @inheritDoc
268
- */ refresh() {
280
+ * @inheritDoc
281
+ */ refresh() {
269
282
  const model = this.editor.model;
270
283
  const selection = model.document.selection;
271
284
  const selectedElement = selection.getSelectedElement() || first(selection.getSelectedBlocks());
@@ -283,70 +296,70 @@ class LinkCommand extends Command {
283
296
  }
284
297
  }
285
298
  /**
286
- * Executes the command.
287
- *
288
- * When the selection is non-collapsed, the `linkHref` attribute will be applied to nodes inside the selection, but only to
289
- * those nodes where the `linkHref` attribute is allowed (disallowed nodes will be omitted).
290
- *
291
- * When the selection is collapsed and is not inside the text with the `linkHref` attribute, a
292
- * new {@link module:engine/model/text~Text text node} with the `linkHref` attribute will be inserted in place of the caret, but
293
- * only if such element is allowed in this place. The `_data` of the inserted text will equal the `href` parameter.
294
- * The selection will be updated to wrap the just inserted text node.
295
- *
296
- * When the selection is collapsed and inside the text with the `linkHref` attribute, the attribute value will be updated.
297
- *
298
- * # Decorators and model attribute management
299
- *
300
- * There is an optional argument to this command that applies or removes model
301
- * {@glink framework/architecture/editing-engine#text-attributes text attributes} brought by
302
- * {@link module:link/utils/manualdecorator~ManualDecorator manual link decorators}.
303
- *
304
- * Text attribute names in the model correspond to the entries in the {@link module:link/linkconfig~LinkConfig#decorators
305
- * configuration}.
306
- * For every decorator configured, a model text attribute exists with the "link" prefix. For example, a `'linkMyDecorator'` attribute
307
- * corresponds to `'myDecorator'` in the configuration.
308
- *
309
- * To learn more about link decorators, check out the {@link module:link/linkconfig~LinkConfig#decorators `config.link.decorators`}
310
- * documentation.
311
- *
312
- * Here is how to manage decorator attributes with the link command:
313
- *
314
- * ```ts
315
- * const linkCommand = editor.commands.get( 'link' );
316
- *
317
- * // Adding a new decorator attribute.
318
- * linkCommand.execute( 'http://example.com', {
319
- * linkIsExternal: true
320
- * } );
321
- *
322
- * // Removing a decorator attribute from the selection.
323
- * linkCommand.execute( 'http://example.com', {
324
- * linkIsExternal: false
325
- * } );
326
- *
327
- * // Adding multiple decorator attributes at the same time.
328
- * linkCommand.execute( 'http://example.com', {
329
- * linkIsExternal: true,
330
- * linkIsDownloadable: true,
331
- * } );
332
- *
333
- * // Removing and adding decorator attributes at the same time.
334
- * linkCommand.execute( 'http://example.com', {
335
- * linkIsExternal: false,
336
- * linkFoo: true,
337
- * linkIsDownloadable: false,
338
- * } );
339
- * ```
340
- *
341
- * **Note**: If the decorator attribute name is not specified, its state remains untouched.
342
- *
343
- * **Note**: {@link module:link/unlinkcommand~UnlinkCommand#execute `UnlinkCommand#execute()`} removes all
344
- * decorator attributes.
345
- *
346
- * @fires execute
347
- * @param href Link destination.
348
- * @param manualDecoratorIds The information about manual decorator attributes to be applied or removed upon execution.
349
- */ execute(href, manualDecoratorIds = {}) {
299
+ * Executes the command.
300
+ *
301
+ * When the selection is non-collapsed, the `linkHref` attribute will be applied to nodes inside the selection, but only to
302
+ * those nodes where the `linkHref` attribute is allowed (disallowed nodes will be omitted).
303
+ *
304
+ * When the selection is collapsed and is not inside the text with the `linkHref` attribute, a
305
+ * new {@link module:engine/model/text~Text text node} with the `linkHref` attribute will be inserted in place of the caret, but
306
+ * only if such element is allowed in this place. The `_data` of the inserted text will equal the `href` parameter.
307
+ * The selection will be updated to wrap the just inserted text node.
308
+ *
309
+ * When the selection is collapsed and inside the text with the `linkHref` attribute, the attribute value will be updated.
310
+ *
311
+ * # Decorators and model attribute management
312
+ *
313
+ * There is an optional argument to this command that applies or removes model
314
+ * {@glink framework/architecture/editing-engine#text-attributes text attributes} brought by
315
+ * {@link module:link/utils/manualdecorator~ManualDecorator manual link decorators}.
316
+ *
317
+ * Text attribute names in the model correspond to the entries in the {@link module:link/linkconfig~LinkConfig#decorators
318
+ * configuration}.
319
+ * For every decorator configured, a model text attribute exists with the "link" prefix. For example, a `'linkMyDecorator'` attribute
320
+ * corresponds to `'myDecorator'` in the configuration.
321
+ *
322
+ * To learn more about link decorators, check out the {@link module:link/linkconfig~LinkConfig#decorators `config.link.decorators`}
323
+ * documentation.
324
+ *
325
+ * Here is how to manage decorator attributes with the link command:
326
+ *
327
+ * ```ts
328
+ * const linkCommand = editor.commands.get( 'link' );
329
+ *
330
+ * // Adding a new decorator attribute.
331
+ * linkCommand.execute( 'http://example.com', {
332
+ * linkIsExternal: true
333
+ * } );
334
+ *
335
+ * // Removing a decorator attribute from the selection.
336
+ * linkCommand.execute( 'http://example.com', {
337
+ * linkIsExternal: false
338
+ * } );
339
+ *
340
+ * // Adding multiple decorator attributes at the same time.
341
+ * linkCommand.execute( 'http://example.com', {
342
+ * linkIsExternal: true,
343
+ * linkIsDownloadable: true,
344
+ * } );
345
+ *
346
+ * // Removing and adding decorator attributes at the same time.
347
+ * linkCommand.execute( 'http://example.com', {
348
+ * linkIsExternal: false,
349
+ * linkFoo: true,
350
+ * linkIsDownloadable: false,
351
+ * } );
352
+ * ```
353
+ *
354
+ * **Note**: If the decorator attribute name is not specified, its state remains untouched.
355
+ *
356
+ * **Note**: {@link module:link/unlinkcommand~UnlinkCommand#execute `UnlinkCommand#execute()`} removes all
357
+ * decorator attributes.
358
+ *
359
+ * @fires execute
360
+ * @param href Link destination.
361
+ * @param manualDecoratorIds The information about manual decorator attributes to be applied or removed upon execution.
362
+ */ execute(href, manualDecoratorIds = {}) {
350
363
  const model = this.editor.model;
351
364
  const selection = model.document.selection;
352
365
  // Stores information about manual decorators to turn them on/off when command is applied.
@@ -442,11 +455,11 @@ class LinkCommand extends Command {
442
455
  });
443
456
  }
444
457
  /**
445
- * Provides information whether a decorator with a given name is present in the currently processed selection.
446
- *
447
- * @param decoratorName The name of the manual decorator used in the model
448
- * @returns The information whether a given decorator is currently present in the selection.
449
- */ _getDecoratorStateFromModel(decoratorName) {
458
+ * Provides information whether a decorator with a given name is present in the currently processed selection.
459
+ *
460
+ * @param decoratorName The name of the manual decorator used in the model
461
+ * @returns The information whether a given decorator is currently present in the selection.
462
+ */ _getDecoratorStateFromModel(decoratorName) {
450
463
  const model = this.editor.model;
451
464
  const selection = model.document.selection;
452
465
  const selectedElement = selection.getSelectedElement();
@@ -458,11 +471,11 @@ class LinkCommand extends Command {
458
471
  return selection.getAttribute(decoratorName);
459
472
  }
460
473
  /**
461
- * Checks whether specified `range` is inside an element that accepts the `linkHref` attribute.
462
- *
463
- * @param range A range to check.
464
- * @param allowedRanges An array of ranges created on elements where the attribute is accepted.
465
- */ _isRangeToUpdate(range, allowedRanges) {
474
+ * Checks whether specified `range` is inside an element that accepts the `linkHref` attribute.
475
+ *
476
+ * @param range A range to check.
477
+ * @param allowedRanges An array of ranges created on elements where the attribute is accepted.
478
+ */ _isRangeToUpdate(range, allowedRanges) {
466
479
  for (const allowedRange of allowedRanges){
467
480
  // A range is inside an element that will have the `linkHref` attribute. Do not modify its nodes.
468
481
  if (allowedRange.containsRange(range)) {
@@ -472,31 +485,18 @@ class LinkCommand extends Command {
472
485
  return true;
473
486
  }
474
487
  /**
475
- * Updates selected link with a new value as its content and as its href attribute.
476
- *
477
- * @param model Model is need to insert content.
478
- * @param writer Writer is need to create text element in model.
479
- * @param range A range where should be inserted content.
480
- * @param href A link value which should be in the href attribute and in the content.
481
- */ _updateLinkContent(model, writer, range, href) {
488
+ * Updates selected link with a new value as its content and as its href attribute.
489
+ *
490
+ * @param model Model is need to insert content.
491
+ * @param writer Writer is need to create text element in model.
492
+ * @param range A range where should be inserted content.
493
+ * @param href A link value which should be in the href attribute and in the content.
494
+ */ _updateLinkContent(model, writer, range, href) {
482
495
  const text = writer.createText(href, {
483
496
  linkHref: href
484
497
  });
485
498
  return model.insertContent(text, range);
486
499
  }
487
- constructor(){
488
- super(...arguments);
489
- /**
490
- * A collection of {@link module:link/utils/manualdecorator~ManualDecorator manual decorators}
491
- * corresponding to the {@link module:link/linkconfig~LinkConfig#decorators decorator configuration}.
492
- *
493
- * You can consider it a model with states of manual decorators added to the currently selected link.
494
- */ this.manualDecorators = new Collection();
495
- /**
496
- * An instance of the helper that ties together all {@link module:link/linkconfig~LinkDecoratorAutomaticDefinition}
497
- * that are used by the {@glink features/link link} and the {@glink features/images/images-linking linking images} features.
498
- */ this.automaticDecorators = new AutomaticDecorators();
499
- }
500
500
  }
501
501
  // Returns a text of a link under the collapsed selection or a selection that contains the entire link.
502
502
  function extractTextFromSelection(selection) {
@@ -516,10 +516,12 @@ function extractTextFromSelection(selection) {
516
516
  }
517
517
  }
518
518
 
519
- class UnlinkCommand extends Command {
519
+ /**
520
+ * The unlink command. It is used by the {@link module:link/link~Link link plugin}.
521
+ */ class UnlinkCommand extends Command {
520
522
  /**
521
- * @inheritDoc
522
- */ refresh() {
523
+ * @inheritDoc
524
+ */ refresh() {
523
525
  const model = this.editor.model;
524
526
  const selection = model.document.selection;
525
527
  const selectedElement = selection.getSelectedElement();
@@ -532,18 +534,18 @@ class UnlinkCommand extends Command {
532
534
  }
533
535
  }
534
536
  /**
535
- * Executes the command.
536
- *
537
- * When the selection is collapsed, it removes the `linkHref` attribute from each node with the same `linkHref` attribute value.
538
- * When the selection is non-collapsed, it removes the `linkHref` attribute from each node in selected ranges.
539
- *
540
- * # Decorators
541
- *
542
- * If {@link module:link/linkconfig~LinkConfig#decorators `config.link.decorators`} is specified,
543
- * all configured decorators are removed together with the `linkHref` attribute.
544
- *
545
- * @fires execute
546
- */ execute() {
537
+ * Executes the command.
538
+ *
539
+ * When the selection is collapsed, it removes the `linkHref` attribute from each node with the same `linkHref` attribute value.
540
+ * When the selection is non-collapsed, it removes the `linkHref` attribute from each node in selected ranges.
541
+ *
542
+ * # Decorators
543
+ *
544
+ * If {@link module:link/linkconfig~LinkConfig#decorators `config.link.decorators`} is specified,
545
+ * all configured decorators are removed together with the `linkHref` attribute.
546
+ *
547
+ * @fires execute
548
+ */ execute() {
547
549
  const editor = this.editor;
548
550
  const model = this.editor.model;
549
551
  const selection = model.document.selection;
@@ -567,28 +569,42 @@ class UnlinkCommand extends Command {
567
569
  }
568
570
  }
569
571
 
570
- class ManualDecorator extends /* #__PURE__ */ ObservableMixin() {
571
- /**
572
- * Returns {@link module:engine/view/matcher~MatcherPattern} with decorator attributes.
573
- *
574
- * @internal
575
- */ _createPattern() {
576
- return {
577
- attributes: this.attributes,
578
- classes: this.classes,
579
- styles: this.styles
580
- };
581
- }
582
- /**
583
- * Creates a new instance of {@link module:link/utils/manualdecorator~ManualDecorator}.
584
- *
585
- * @param config.id The name of the attribute used in the model that represents a given manual decorator.
586
- * For example: `'linkIsExternal'`.
587
- * @param config.label The label used in the user interface to toggle the manual decorator.
588
- * @param config.attributes A set of attributes added to output data when the decorator is active for a specific link.
589
- * Attributes should keep the format of attributes defined in {@link module:engine/view/elementdefinition~ElementDefinition}.
590
- * @param [config.defaultValue] Controls whether the decorator is "on" by default.
591
- */ constructor({ id, label, attributes, classes, styles, defaultValue }){
572
+ /**
573
+ * Helper class that stores manual decorators with observable {@link module:link/utils/manualdecorator~ManualDecorator#value}
574
+ * to support integration with the UI state. An instance of this class is a model with the state of individual manual decorators.
575
+ * These decorators are kept as collections in {@link module:link/linkcommand~LinkCommand#manualDecorators}.
576
+ */ class ManualDecorator extends /* #__PURE__ */ ObservableMixin() {
577
+ /**
578
+ * An ID of a manual decorator which is the name of the attribute in the model, for example: 'linkManualDecorator0'.
579
+ */ id;
580
+ /**
581
+ * The default value of manual decorator.
582
+ */ defaultValue;
583
+ /**
584
+ * The label used in the user interface to toggle the manual decorator.
585
+ */ label;
586
+ /**
587
+ * A set of attributes added to downcasted data when the decorator is activated for a specific link.
588
+ * Attributes should be added in a form of attributes defined in {@link module:engine/view/elementdefinition~ElementDefinition}.
589
+ */ attributes;
590
+ /**
591
+ * A set of classes added to downcasted data when the decorator is activated for a specific link.
592
+ * Classes should be added in a form of classes defined in {@link module:engine/view/elementdefinition~ElementDefinition}.
593
+ */ classes;
594
+ /**
595
+ * A set of styles added to downcasted data when the decorator is activated for a specific link.
596
+ * Styles should be added in a form of styles defined in {@link module:engine/view/elementdefinition~ElementDefinition}.
597
+ */ styles;
598
+ /**
599
+ * Creates a new instance of {@link module:link/utils/manualdecorator~ManualDecorator}.
600
+ *
601
+ * @param config.id The name of the attribute used in the model that represents a given manual decorator.
602
+ * For example: `'linkIsExternal'`.
603
+ * @param config.label The label used in the user interface to toggle the manual decorator.
604
+ * @param config.attributes A set of attributes added to output data when the decorator is active for a specific link.
605
+ * Attributes should keep the format of attributes defined in {@link module:engine/view/elementdefinition~ElementDefinition}.
606
+ * @param [config.defaultValue] Controls whether the decorator is "on" by default.
607
+ */ constructor({ id, label, attributes, classes, styles, defaultValue }){
592
608
  super();
593
609
  this.id = id;
594
610
  this.set('value', undefined);
@@ -598,21 +614,37 @@ class ManualDecorator extends /* #__PURE__ */ ObservableMixin() {
598
614
  this.classes = classes;
599
615
  this.styles = styles;
600
616
  }
617
+ /**
618
+ * Returns {@link module:engine/view/matcher~MatcherPattern} with decorator attributes.
619
+ *
620
+ * @internal
621
+ */ _createPattern() {
622
+ return {
623
+ attributes: this.attributes,
624
+ classes: this.classes,
625
+ styles: this.styles
626
+ };
627
+ }
601
628
  }
602
629
 
603
630
  const HIGHLIGHT_CLASS = 'ck-link_selected';
604
631
  const DECORATOR_AUTOMATIC = 'automatic';
605
632
  const DECORATOR_MANUAL = 'manual';
606
633
  const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
607
- class LinkEditing extends Plugin {
634
+ /**
635
+ * The link engine feature.
636
+ *
637
+ * It introduces the `linkHref="url"` attribute in the model which renders to the view as a `<a href="url">` element
638
+ * as well as `'link'` and `'unlink'` commands.
639
+ */ class LinkEditing extends Plugin {
608
640
  /**
609
- * @inheritDoc
610
- */ static get pluginName() {
641
+ * @inheritDoc
642
+ */ static get pluginName() {
611
643
  return 'LinkEditing';
612
644
  }
613
645
  /**
614
- * @inheritDoc
615
- */ static get requires() {
646
+ * @inheritDoc
647
+ */ static get requires() {
616
648
  // Clipboard is required for handling cut and paste events while typing over the link.
617
649
  return [
618
650
  TwoStepCaretMovement,
@@ -621,8 +653,17 @@ class LinkEditing extends Plugin {
621
653
  ];
622
654
  }
623
655
  /**
624
- * @inheritDoc
625
- */ init() {
656
+ * @inheritDoc
657
+ */ constructor(editor){
658
+ super(editor);
659
+ editor.config.define('link', {
660
+ allowCreatingEmptyLinks: false,
661
+ addTargetToExternalLinks: false
662
+ });
663
+ }
664
+ /**
665
+ * @inheritDoc
666
+ */ init() {
626
667
  const editor = this.editor;
627
668
  const allowedProtocols = this.editor.config.get('link.allowedProtocols');
628
669
  // Allow link attribute on all inline nodes.
@@ -670,14 +711,14 @@ class LinkEditing extends Plugin {
670
711
  this._enableClipboardIntegration();
671
712
  }
672
713
  /**
673
- * Processes an array of configured {@link module:link/linkconfig~LinkDecoratorAutomaticDefinition automatic decorators}
674
- * and registers a {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher downcast dispatcher}
675
- * for each one of them. Downcast dispatchers are obtained using the
676
- * {@link module:link/utils/automaticdecorators~AutomaticDecorators#getDispatcher} method.
677
- *
678
- * **Note**: This method also activates the automatic external link decorator if enabled with
679
- * {@link module:link/linkconfig~LinkConfig#addTargetToExternalLinks `config.link.addTargetToExternalLinks`}.
680
- */ _enableAutomaticDecorators(automaticDecoratorDefinitions) {
714
+ * Processes an array of configured {@link module:link/linkconfig~LinkDecoratorAutomaticDefinition automatic decorators}
715
+ * and registers a {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher downcast dispatcher}
716
+ * for each one of them. Downcast dispatchers are obtained using the
717
+ * {@link module:link/utils/automaticdecorators~AutomaticDecorators#getDispatcher} method.
718
+ *
719
+ * **Note**: This method also activates the automatic external link decorator if enabled with
720
+ * {@link module:link/linkconfig~LinkConfig#addTargetToExternalLinks `config.link.addTargetToExternalLinks`}.
721
+ */ _enableAutomaticDecorators(automaticDecoratorDefinitions) {
681
722
  const editor = this.editor;
682
723
  // Store automatic decorators in the command instance as we do the same with manual decorators.
683
724
  // Thanks to that, `LinkImageEditing` plugin can re-use the same definitions.
@@ -701,14 +742,14 @@ class LinkEditing extends Plugin {
701
742
  }
702
743
  }
703
744
  /**
704
- * Processes an array of configured {@link module:link/linkconfig~LinkDecoratorManualDefinition manual decorators},
705
- * transforms them into {@link module:link/utils/manualdecorator~ManualDecorator} instances and stores them in the
706
- * {@link module:link/linkcommand~LinkCommand#manualDecorators} collection (a model for manual decorators state).
707
- *
708
- * Also registers an {@link module:engine/conversion/downcasthelpers~DowncastHelpers#attributeToElement attribute-to-element}
709
- * converter for each manual decorator and extends the {@link module:engine/model/schema~Schema model's schema}
710
- * with adequate model attributes.
711
- */ _enableManualDecorators(manualDecoratorDefinitions) {
745
+ * Processes an array of configured {@link module:link/linkconfig~LinkDecoratorManualDefinition manual decorators},
746
+ * transforms them into {@link module:link/utils/manualdecorator~ManualDecorator} instances and stores them in the
747
+ * {@link module:link/linkcommand~LinkCommand#manualDecorators} collection (a model for manual decorators state).
748
+ *
749
+ * Also registers an {@link module:engine/conversion/downcasthelpers~DowncastHelpers#attributeToElement attribute-to-element}
750
+ * converter for each manual decorator and extends the {@link module:engine/model/schema~Schema model's schema}
751
+ * with adequate model attributes.
752
+ */ _enableManualDecorators(manualDecoratorDefinitions) {
712
753
  if (!manualDecoratorDefinitions.length) {
713
754
  return;
714
755
  }
@@ -756,9 +797,9 @@ class LinkEditing extends Plugin {
756
797
  });
757
798
  }
758
799
  /**
759
- * Attaches handlers for {@link module:engine/view/document~Document#event:enter} and
760
- * {@link module:engine/view/document~Document#event:click} to enable link following.
761
- */ _enableLinkOpen() {
800
+ * Attaches handlers for {@link module:engine/view/document~Document#event:enter} and
801
+ * {@link module:engine/view/document~Document#event:click} to enable link following.
802
+ */ _enableLinkOpen() {
762
803
  const editor = this.editor;
763
804
  const view = editor.editing.view;
764
805
  const viewDocument = view.document;
@@ -797,10 +838,10 @@ class LinkEditing extends Plugin {
797
838
  });
798
839
  }
799
840
  /**
800
- * Watches the DocumentSelection attribute changes and removes link decorator attributes when the linkHref attribute is removed.
801
- *
802
- * This is to ensure that there is no left-over link decorator attributes on the document selection that is no longer in a link.
803
- */ _enableSelectionAttributesFixer() {
841
+ * Watches the DocumentSelection attribute changes and removes link decorator attributes when the linkHref attribute is removed.
842
+ *
843
+ * This is to ensure that there is no left-over link decorator attributes on the document selection that is no longer in a link.
844
+ */ _enableSelectionAttributesFixer() {
804
845
  const editor = this.editor;
805
846
  const model = editor.model;
806
847
  const selection = model.document.selection;
@@ -814,8 +855,8 @@ class LinkEditing extends Plugin {
814
855
  });
815
856
  }
816
857
  /**
817
- * Enables URL fixing on pasting.
818
- */ _enableClipboardIntegration() {
858
+ * Enables URL fixing on pasting.
859
+ */ _enableClipboardIntegration() {
819
860
  const editor = this.editor;
820
861
  const model = editor.model;
821
862
  const defaultProtocol = this.editor.config.get('link.defaultProtocol');
@@ -834,15 +875,6 @@ class LinkEditing extends Plugin {
834
875
  });
835
876
  });
836
877
  }
837
- /**
838
- * @inheritDoc
839
- */ constructor(editor){
840
- super(editor);
841
- editor.config.define('link', {
842
- allowCreatingEmptyLinks: false,
843
- addTargetToExternalLinks: false
844
- });
845
- }
846
878
  }
847
879
  /**
848
880
  * Make the selection free of link-related model attributes.
@@ -861,22 +893,105 @@ class LinkEditing extends Plugin {
861
893
  return textAttributes.filter((attribute)=>attribute.startsWith('link'));
862
894
  }
863
895
 
864
- class LinkFormView extends View {
865
- /**
866
- * Obtains the state of the {@link module:ui/button/switchbuttonview~SwitchButtonView switch buttons} representing
867
- * {@link module:link/linkcommand~LinkCommand#manualDecorators manual link decorators}
868
- * in the {@link module:link/ui/linkformview~LinkFormView}.
869
- *
870
- * @returns Key-value pairs, where the key is the name of the decorator and the value is its state.
871
- */ getDecoratorSwitchesState() {
896
+ /**
897
+ * The link form view controller class.
898
+ *
899
+ * See {@link module:link/ui/linkformview~LinkFormView}.
900
+ */ class LinkFormView extends View {
901
+ /**
902
+ * Tracks information about DOM focus in the form.
903
+ */ focusTracker = new FocusTracker();
904
+ /**
905
+ * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
906
+ */ keystrokes = new KeystrokeHandler();
907
+ /**
908
+ * The URL input view.
909
+ */ urlInputView;
910
+ /**
911
+ * The Save button view.
912
+ */ saveButtonView;
913
+ /**
914
+ * The Cancel button view.
915
+ */ cancelButtonView;
916
+ /**
917
+ * A collection of {@link module:ui/button/switchbuttonview~SwitchButtonView},
918
+ * which corresponds to {@link module:link/linkcommand~LinkCommand#manualDecorators manual decorators}
919
+ * configured in the editor.
920
+ */ _manualDecoratorSwitches;
921
+ /**
922
+ * A collection of child views in the form.
923
+ */ children;
924
+ /**
925
+ * An array of form validators used by {@link #isValid}.
926
+ */ _validators;
927
+ /**
928
+ * A collection of views that can be focused in the form.
929
+ */ _focusables = new ViewCollection();
930
+ /**
931
+ * Helps cycling over {@link #_focusables} in the form.
932
+ */ _focusCycler;
933
+ /**
934
+ * Creates an instance of the {@link module:link/ui/linkformview~LinkFormView} class.
935
+ *
936
+ * Also see {@link #render}.
937
+ *
938
+ * @param locale The localization services instance.
939
+ * @param linkCommand Reference to {@link module:link/linkcommand~LinkCommand}.
940
+ * @param validators Form validators used by {@link #isValid}.
941
+ */ constructor(locale, linkCommand, validators){
942
+ super(locale);
943
+ const t = locale.t;
944
+ this._validators = validators;
945
+ this.urlInputView = this._createUrlInput();
946
+ this.saveButtonView = this._createButton(t('Save'), icons.check, 'ck-button-save');
947
+ this.saveButtonView.type = 'submit';
948
+ this.cancelButtonView = this._createButton(t('Cancel'), icons.cancel, 'ck-button-cancel', 'cancel');
949
+ this._manualDecoratorSwitches = this._createManualDecoratorSwitches(linkCommand);
950
+ this.children = this._createFormChildren(linkCommand.manualDecorators);
951
+ this._focusCycler = new FocusCycler({
952
+ focusables: this._focusables,
953
+ focusTracker: this.focusTracker,
954
+ keystrokeHandler: this.keystrokes,
955
+ actions: {
956
+ // Navigate form fields backwards using the Shift + Tab keystroke.
957
+ focusPrevious: 'shift + tab',
958
+ // Navigate form fields forwards using the Tab key.
959
+ focusNext: 'tab'
960
+ }
961
+ });
962
+ const classList = [
963
+ 'ck',
964
+ 'ck-link-form',
965
+ 'ck-responsive-form'
966
+ ];
967
+ if (linkCommand.manualDecorators.length) {
968
+ classList.push('ck-link-form_layout-vertical', 'ck-vertical-form');
969
+ }
970
+ this.setTemplate({
971
+ tag: 'form',
972
+ attributes: {
973
+ class: classList,
974
+ // https://github.com/ckeditor/ckeditor5-link/issues/90
975
+ tabindex: '-1'
976
+ },
977
+ children: this.children
978
+ });
979
+ }
980
+ /**
981
+ * Obtains the state of the {@link module:ui/button/switchbuttonview~SwitchButtonView switch buttons} representing
982
+ * {@link module:link/linkcommand~LinkCommand#manualDecorators manual link decorators}
983
+ * in the {@link module:link/ui/linkformview~LinkFormView}.
984
+ *
985
+ * @returns Key-value pairs, where the key is the name of the decorator and the value is its state.
986
+ */ getDecoratorSwitchesState() {
872
987
  return Array.from(this._manualDecoratorSwitches).reduce((accumulator, switchButton)=>{
873
988
  accumulator[switchButton.name] = switchButton.isOn;
874
989
  return accumulator;
875
990
  }, {});
876
991
  }
877
992
  /**
878
- * @inheritDoc
879
- */ render() {
993
+ * @inheritDoc
994
+ */ render() {
880
995
  super.render();
881
996
  submitHandler({
882
997
  view: this
@@ -897,20 +1012,20 @@ class LinkFormView extends View {
897
1012
  this.keystrokes.listenTo(this.element);
898
1013
  }
899
1014
  /**
900
- * @inheritDoc
901
- */ destroy() {
1015
+ * @inheritDoc
1016
+ */ destroy() {
902
1017
  super.destroy();
903
1018
  this.focusTracker.destroy();
904
1019
  this.keystrokes.destroy();
905
1020
  }
906
1021
  /**
907
- * Focuses the fist {@link #_focusables} in the form.
908
- */ focus() {
1022
+ * Focuses the fist {@link #_focusables} in the form.
1023
+ */ focus() {
909
1024
  this._focusCycler.focusFirst();
910
1025
  }
911
1026
  /**
912
- * Validates the form and returns `false` when some fields are invalid.
913
- */ isValid() {
1027
+ * Validates the form and returns `false` when some fields are invalid.
1028
+ */ isValid() {
914
1029
  this.resetFormStatus();
915
1030
  for (const validator of this._validators){
916
1031
  const errorText = validator(this);
@@ -924,32 +1039,32 @@ class LinkFormView extends View {
924
1039
  return true;
925
1040
  }
926
1041
  /**
927
- * Cleans up the supplementary error and information text of the {@link #urlInputView}
928
- * bringing them back to the state when the form has been displayed for the first time.
929
- *
930
- * See {@link #isValid}.
931
- */ resetFormStatus() {
1042
+ * Cleans up the supplementary error and information text of the {@link #urlInputView}
1043
+ * bringing them back to the state when the form has been displayed for the first time.
1044
+ *
1045
+ * See {@link #isValid}.
1046
+ */ resetFormStatus() {
932
1047
  this.urlInputView.errorText = null;
933
1048
  }
934
1049
  /**
935
- * Creates a labeled input view.
936
- *
937
- * @returns Labeled field view instance.
938
- */ _createUrlInput() {
1050
+ * Creates a labeled input view.
1051
+ *
1052
+ * @returns Labeled field view instance.
1053
+ */ _createUrlInput() {
939
1054
  const t = this.locale.t;
940
1055
  const labeledInput = new LabeledFieldView(this.locale, createLabeledInputText);
941
1056
  labeledInput.label = t('Link URL');
942
1057
  return labeledInput;
943
1058
  }
944
1059
  /**
945
- * Creates a button view.
946
- *
947
- * @param label The button label.
948
- * @param icon The button icon.
949
- * @param className The additional button CSS class name.
950
- * @param eventName An event name that the `ButtonView#execute` event will be delegated to.
951
- * @returns The button view instance.
952
- */ _createButton(label, icon, className, eventName) {
1060
+ * Creates a button view.
1061
+ *
1062
+ * @param label The button label.
1063
+ * @param icon The button icon.
1064
+ * @param className The additional button CSS class name.
1065
+ * @param eventName An event name that the `ButtonView#execute` event will be delegated to.
1066
+ * @returns The button view instance.
1067
+ */ _createButton(label, icon, className, eventName) {
953
1068
  const button = new ButtonView(this.locale);
954
1069
  button.set({
955
1070
  label,
@@ -967,12 +1082,12 @@ class LinkFormView extends View {
967
1082
  return button;
968
1083
  }
969
1084
  /**
970
- * Populates {@link module:ui/viewcollection~ViewCollection} of {@link module:ui/button/switchbuttonview~SwitchButtonView}
971
- * made based on {@link module:link/linkcommand~LinkCommand#manualDecorators}.
972
- *
973
- * @param linkCommand A reference to the link command.
974
- * @returns ViewCollection of switch buttons.
975
- */ _createManualDecoratorSwitches(linkCommand) {
1085
+ * Populates {@link module:ui/viewcollection~ViewCollection} of {@link module:ui/button/switchbuttonview~SwitchButtonView}
1086
+ * made based on {@link module:link/linkcommand~LinkCommand#manualDecorators}.
1087
+ *
1088
+ * @param linkCommand A reference to the link command.
1089
+ * @returns ViewCollection of switch buttons.
1090
+ */ _createManualDecoratorSwitches(linkCommand) {
976
1091
  const switches = this.createCollection();
977
1092
  for (const manualDecorator of linkCommand.manualDecorators){
978
1093
  const switchButton = new SwitchButtonView(this.locale);
@@ -995,16 +1110,16 @@ class LinkFormView extends View {
995
1110
  return switches;
996
1111
  }
997
1112
  /**
998
- * Populates the {@link #children} collection of the form.
999
- *
1000
- * If {@link module:link/linkcommand~LinkCommand#manualDecorators manual decorators} are configured in the editor, it creates an
1001
- * additional `View` wrapping all {@link #_manualDecoratorSwitches} switch buttons corresponding
1002
- * to these decorators.
1003
- *
1004
- * @param manualDecorators A reference to
1005
- * the collection of manual decorators stored in the link command.
1006
- * @returns The children of link form view.
1007
- */ _createFormChildren(manualDecorators) {
1113
+ * Populates the {@link #children} collection of the form.
1114
+ *
1115
+ * If {@link module:link/linkcommand~LinkCommand#manualDecorators manual decorators} are configured in the editor, it creates an
1116
+ * additional `View` wrapping all {@link #_manualDecoratorSwitches} switch buttons corresponding
1117
+ * to these decorators.
1118
+ *
1119
+ * @param manualDecorators A reference to
1120
+ * the collection of manual decorators stored in the link command.
1121
+ * @returns The children of link form view.
1122
+ */ _createFormChildren(manualDecorators) {
1008
1123
  const children = this.createCollection();
1009
1124
  children.add(this.urlInputView);
1010
1125
  if (manualDecorators.length) {
@@ -1038,81 +1153,89 @@ class LinkFormView extends View {
1038
1153
  return children;
1039
1154
  }
1040
1155
  /**
1041
- * The native DOM `value` of the {@link #urlInputView} element.
1042
- *
1043
- * **Note**: Do not confuse it with the {@link module:ui/inputtext/inputtextview~InputTextView#value}
1044
- * which works one way only and may not represent the actual state of the component in the DOM.
1045
- */ get url() {
1156
+ * The native DOM `value` of the {@link #urlInputView} element.
1157
+ *
1158
+ * **Note**: Do not confuse it with the {@link module:ui/inputtext/inputtextview~InputTextView#value}
1159
+ * which works one way only and may not represent the actual state of the component in the DOM.
1160
+ */ get url() {
1046
1161
  const { element } = this.urlInputView.fieldView;
1047
1162
  if (!element) {
1048
1163
  return null;
1049
1164
  }
1050
1165
  return element.value.trim();
1051
1166
  }
1167
+ }
1168
+
1169
+ var unlinkIcon = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m11.077 15 .991-1.416a.75.75 0 1 1 1.229.86l-1.148 1.64a.748.748 0 0 1-.217.206 5.251 5.251 0 0 1-8.503-5.955.741.741 0 0 1 .12-.274l1.147-1.639a.75.75 0 1 1 1.228.86L4.933 10.7l.006.003a3.75 3.75 0 0 0 6.132 4.294l.006.004zm5.494-5.335a.748.748 0 0 1-.12.274l-1.147 1.639a.75.75 0 1 1-1.228-.86l.86-1.23a3.75 3.75 0 0 0-6.144-4.301l-.86 1.229a.75.75 0 0 1-1.229-.86l1.148-1.64a.748.748 0 0 1 .217-.206 5.251 5.251 0 0 1 8.503 5.955zm-4.563-2.532a.75.75 0 0 1 .184 1.045l-3.155 4.505a.75.75 0 1 1-1.229-.86l3.155-4.506a.75.75 0 0 1 1.045-.184zm4.919 10.562-1.414 1.414a.75.75 0 1 1-1.06-1.06l1.414-1.415-1.415-1.414a.75.75 0 0 1 1.061-1.06l1.414 1.414 1.414-1.415a.75.75 0 0 1 1.061 1.061l-1.414 1.414 1.414 1.415a.75.75 0 0 1-1.06 1.06l-1.415-1.414z\"/></svg>";
1170
+
1171
+ /**
1172
+ * The link actions view class. This view displays the link preview, allows
1173
+ * unlinking or editing the link.
1174
+ */ class LinkActionsView extends View {
1175
+ /**
1176
+ * Tracks information about DOM focus in the actions.
1177
+ */ focusTracker = new FocusTracker();
1178
+ /**
1179
+ * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
1180
+ */ keystrokes = new KeystrokeHandler();
1052
1181
  /**
1053
- * Creates an instance of the {@link module:link/ui/linkformview~LinkFormView} class.
1054
- *
1055
- * Also see {@link #render}.
1056
- *
1057
- * @param locale The localization services instance.
1058
- * @param linkCommand Reference to {@link module:link/linkcommand~LinkCommand}.
1059
- * @param validators Form validators used by {@link #isValid}.
1060
- */ constructor(locale, linkCommand, validators){
1182
+ * The href preview view.
1183
+ */ previewButtonView;
1184
+ /**
1185
+ * The unlink button view.
1186
+ */ unlinkButtonView;
1187
+ /**
1188
+ * The edit link button view.
1189
+ */ editButtonView;
1190
+ /**
1191
+ * A collection of views that can be focused in the view.
1192
+ */ _focusables = new ViewCollection();
1193
+ /**
1194
+ * Helps cycling over {@link #_focusables} in the view.
1195
+ */ _focusCycler;
1196
+ _linkConfig;
1197
+ /**
1198
+ * @inheritDoc
1199
+ */ constructor(locale, linkConfig = {}){
1061
1200
  super(locale);
1062
- /**
1063
- * Tracks information about DOM focus in the form.
1064
- */ this.focusTracker = new FocusTracker();
1065
- /**
1066
- * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
1067
- */ this.keystrokes = new KeystrokeHandler();
1068
- /**
1069
- * A collection of views that can be focused in the form.
1070
- */ this._focusables = new ViewCollection();
1071
1201
  const t = locale.t;
1072
- this._validators = validators;
1073
- this.urlInputView = this._createUrlInput();
1074
- this.saveButtonView = this._createButton(t('Save'), icons.check, 'ck-button-save');
1075
- this.saveButtonView.type = 'submit';
1076
- this.cancelButtonView = this._createButton(t('Cancel'), icons.cancel, 'ck-button-cancel', 'cancel');
1077
- this._manualDecoratorSwitches = this._createManualDecoratorSwitches(linkCommand);
1078
- this.children = this._createFormChildren(linkCommand.manualDecorators);
1202
+ this.previewButtonView = this._createPreviewButton();
1203
+ this.unlinkButtonView = this._createButton(t('Unlink'), unlinkIcon, 'unlink');
1204
+ this.editButtonView = this._createButton(t('Edit link'), icons.pencil, 'edit');
1205
+ this.set('href', undefined);
1206
+ this._linkConfig = linkConfig;
1079
1207
  this._focusCycler = new FocusCycler({
1080
1208
  focusables: this._focusables,
1081
1209
  focusTracker: this.focusTracker,
1082
1210
  keystrokeHandler: this.keystrokes,
1083
1211
  actions: {
1084
- // Navigate form fields backwards using the Shift + Tab keystroke.
1212
+ // Navigate fields backwards using the Shift + Tab keystroke.
1085
1213
  focusPrevious: 'shift + tab',
1086
- // Navigate form fields forwards using the Tab key.
1214
+ // Navigate fields forwards using the Tab key.
1087
1215
  focusNext: 'tab'
1088
1216
  }
1089
1217
  });
1090
- const classList = [
1091
- 'ck',
1092
- 'ck-link-form',
1093
- 'ck-responsive-form'
1094
- ];
1095
- if (linkCommand.manualDecorators.length) {
1096
- classList.push('ck-link-form_layout-vertical', 'ck-vertical-form');
1097
- }
1098
1218
  this.setTemplate({
1099
- tag: 'form',
1219
+ tag: 'div',
1100
1220
  attributes: {
1101
- class: classList,
1221
+ class: [
1222
+ 'ck',
1223
+ 'ck-link-actions',
1224
+ 'ck-responsive-form'
1225
+ ],
1102
1226
  // https://github.com/ckeditor/ckeditor5-link/issues/90
1103
1227
  tabindex: '-1'
1104
1228
  },
1105
- children: this.children
1229
+ children: [
1230
+ this.previewButtonView,
1231
+ this.editButtonView,
1232
+ this.unlinkButtonView
1233
+ ]
1106
1234
  });
1107
1235
  }
1108
- }
1109
-
1110
- var unlinkIcon = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m11.077 15 .991-1.416a.75.75 0 1 1 1.229.86l-1.148 1.64a.748.748 0 0 1-.217.206 5.251 5.251 0 0 1-8.503-5.955.741.741 0 0 1 .12-.274l1.147-1.639a.75.75 0 1 1 1.228.86L4.933 10.7l.006.003a3.75 3.75 0 0 0 6.132 4.294l.006.004zm5.494-5.335a.748.748 0 0 1-.12.274l-1.147 1.639a.75.75 0 1 1-1.228-.86l.86-1.23a3.75 3.75 0 0 0-6.144-4.301l-.86 1.229a.75.75 0 0 1-1.229-.86l1.148-1.64a.748.748 0 0 1 .217-.206 5.251 5.251 0 0 1 8.503 5.955zm-4.563-2.532a.75.75 0 0 1 .184 1.045l-3.155 4.505a.75.75 0 1 1-1.229-.86l3.155-4.506a.75.75 0 0 1 1.045-.184zm4.919 10.562-1.414 1.414a.75.75 0 1 1-1.06-1.06l1.414-1.415-1.415-1.414a.75.75 0 0 1 1.061-1.06l1.414 1.414 1.414-1.415a.75.75 0 0 1 1.061 1.061l-1.414 1.414 1.414 1.415a.75.75 0 0 1-1.06 1.06l-1.415-1.414z\"/></svg>";
1111
-
1112
- class LinkActionsView extends View {
1113
1236
  /**
1114
- * @inheritDoc
1115
- */ render() {
1237
+ * @inheritDoc
1238
+ */ render() {
1116
1239
  super.render();
1117
1240
  const childViews = [
1118
1241
  this.previewButtonView,
@@ -1129,25 +1252,25 @@ class LinkActionsView extends View {
1129
1252
  this.keystrokes.listenTo(this.element);
1130
1253
  }
1131
1254
  /**
1132
- * @inheritDoc
1133
- */ destroy() {
1255
+ * @inheritDoc
1256
+ */ destroy() {
1134
1257
  super.destroy();
1135
1258
  this.focusTracker.destroy();
1136
1259
  this.keystrokes.destroy();
1137
1260
  }
1138
1261
  /**
1139
- * Focuses the fist {@link #_focusables} in the actions.
1140
- */ focus() {
1262
+ * Focuses the fist {@link #_focusables} in the actions.
1263
+ */ focus() {
1141
1264
  this._focusCycler.focusFirst();
1142
1265
  }
1143
1266
  /**
1144
- * Creates a button view.
1145
- *
1146
- * @param label The button label.
1147
- * @param icon The button icon.
1148
- * @param eventName An event name that the `ButtonView#execute` event will be delegated to.
1149
- * @returns The button view instance.
1150
- */ _createButton(label, icon, eventName) {
1267
+ * Creates a button view.
1268
+ *
1269
+ * @param label The button label.
1270
+ * @param icon The button icon.
1271
+ * @param eventName An event name that the `ButtonView#execute` event will be delegated to.
1272
+ * @returns The button view instance.
1273
+ */ _createButton(label, icon, eventName) {
1151
1274
  const button = new ButtonView(this.locale);
1152
1275
  button.set({
1153
1276
  label,
@@ -1158,10 +1281,10 @@ class LinkActionsView extends View {
1158
1281
  return button;
1159
1282
  }
1160
1283
  /**
1161
- * Creates a link href preview button.
1162
- *
1163
- * @returns The button view instance.
1164
- */ _createPreviewButton() {
1284
+ * Creates a link href preview button.
1285
+ *
1286
+ * @returns The button view instance.
1287
+ */ _createPreviewButton() {
1165
1288
  const button = new ButtonView(this.locale);
1166
1289
  const bind = this.bindTemplate;
1167
1290
  const t = this.t;
@@ -1188,75 +1311,41 @@ class LinkActionsView extends View {
1188
1311
  button.template.eventListeners = {};
1189
1312
  return button;
1190
1313
  }
1191
- /**
1192
- * @inheritDoc
1193
- */ constructor(locale, linkConfig = {}){
1194
- super(locale);
1195
- /**
1196
- * Tracks information about DOM focus in the actions.
1197
- */ this.focusTracker = new FocusTracker();
1198
- /**
1199
- * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
1200
- */ this.keystrokes = new KeystrokeHandler();
1201
- /**
1202
- * A collection of views that can be focused in the view.
1203
- */ this._focusables = new ViewCollection();
1204
- const t = locale.t;
1205
- this.previewButtonView = this._createPreviewButton();
1206
- this.unlinkButtonView = this._createButton(t('Unlink'), unlinkIcon, 'unlink');
1207
- this.editButtonView = this._createButton(t('Edit link'), icons.pencil, 'edit');
1208
- this.set('href', undefined);
1209
- this._linkConfig = linkConfig;
1210
- this._focusCycler = new FocusCycler({
1211
- focusables: this._focusables,
1212
- focusTracker: this.focusTracker,
1213
- keystrokeHandler: this.keystrokes,
1214
- actions: {
1215
- // Navigate fields backwards using the Shift + Tab keystroke.
1216
- focusPrevious: 'shift + tab',
1217
- // Navigate fields forwards using the Tab key.
1218
- focusNext: 'tab'
1219
- }
1220
- });
1221
- this.setTemplate({
1222
- tag: 'div',
1223
- attributes: {
1224
- class: [
1225
- 'ck',
1226
- 'ck-link-actions',
1227
- 'ck-responsive-form'
1228
- ],
1229
- // https://github.com/ckeditor/ckeditor5-link/issues/90
1230
- tabindex: '-1'
1231
- },
1232
- children: [
1233
- this.previewButtonView,
1234
- this.editButtonView,
1235
- this.unlinkButtonView
1236
- ]
1237
- });
1238
- }
1239
1314
  }
1240
1315
 
1241
1316
  var linkIcon = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m11.077 15 .991-1.416a.75.75 0 1 1 1.229.86l-1.148 1.64a.748.748 0 0 1-.217.206 5.251 5.251 0 0 1-8.503-5.955.741.741 0 0 1 .12-.274l1.147-1.639a.75.75 0 1 1 1.228.86L4.933 10.7l.006.003a3.75 3.75 0 0 0 6.132 4.294l.006.004zm5.494-5.335a.748.748 0 0 1-.12.274l-1.147 1.639a.75.75 0 1 1-1.228-.86l.86-1.23a3.75 3.75 0 0 0-6.144-4.301l-.86 1.229a.75.75 0 0 1-1.229-.86l1.148-1.64a.748.748 0 0 1 .217-.206 5.251 5.251 0 0 1 8.503 5.955zm-4.563-2.532a.75.75 0 0 1 .184 1.045l-3.155 4.505a.75.75 0 1 1-1.229-.86l3.155-4.506a.75.75 0 0 1 1.045-.184z\"/></svg>";
1242
1317
 
1243
1318
  const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
1244
- class LinkUI extends Plugin {
1319
+ /**
1320
+ * The link UI plugin. It introduces the `'link'` and `'unlink'` buttons and support for the <kbd>Ctrl+K</kbd> keystroke.
1321
+ *
1322
+ * It uses the
1323
+ * {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon plugin}.
1324
+ */ class LinkUI extends Plugin {
1325
+ /**
1326
+ * The actions view displayed inside of the balloon.
1327
+ */ actionsView = null;
1245
1328
  /**
1246
- * @inheritDoc
1247
- */ static get requires() {
1329
+ * The form view displayed inside the balloon.
1330
+ */ formView = null;
1331
+ /**
1332
+ * The contextual balloon plugin instance.
1333
+ */ _balloon;
1334
+ /**
1335
+ * @inheritDoc
1336
+ */ static get requires() {
1248
1337
  return [
1249
1338
  ContextualBalloon
1250
1339
  ];
1251
1340
  }
1252
1341
  /**
1253
- * @inheritDoc
1254
- */ static get pluginName() {
1342
+ * @inheritDoc
1343
+ */ static get pluginName() {
1255
1344
  return 'LinkUI';
1256
1345
  }
1257
1346
  /**
1258
- * @inheritDoc
1259
- */ init() {
1347
+ * @inheritDoc
1348
+ */ init() {
1260
1349
  const editor = this.editor;
1261
1350
  const t = this.editor.t;
1262
1351
  editor.editing.view.addObserver(ClickObserver);
@@ -1308,8 +1397,8 @@ class LinkUI extends Plugin {
1308
1397
  });
1309
1398
  }
1310
1399
  /**
1311
- * @inheritDoc
1312
- */ destroy() {
1400
+ * @inheritDoc
1401
+ */ destroy() {
1313
1402
  super.destroy();
1314
1403
  // Destroy created UI components as they are not automatically destroyed (see ckeditor5#1341).
1315
1404
  if (this.formView) {
@@ -1320,16 +1409,16 @@ class LinkUI extends Plugin {
1320
1409
  }
1321
1410
  }
1322
1411
  /**
1323
- * Creates views.
1324
- */ _createViews() {
1412
+ * Creates views.
1413
+ */ _createViews() {
1325
1414
  this.actionsView = this._createActionsView();
1326
1415
  this.formView = this._createFormView();
1327
1416
  // Attach lifecycle actions to the the balloon.
1328
1417
  this._enableUserBalloonInteractions();
1329
1418
  }
1330
1419
  /**
1331
- * Creates the {@link module:link/ui/linkactionsview~LinkActionsView} instance.
1332
- */ _createActionsView() {
1420
+ * Creates the {@link module:link/ui/linkactionsview~LinkActionsView} instance.
1421
+ */ _createActionsView() {
1333
1422
  const editor = this.editor;
1334
1423
  const actionsView = new LinkActionsView(editor.locale, editor.config.get('link'));
1335
1424
  const linkCommand = editor.commands.get('link');
@@ -1359,8 +1448,8 @@ class LinkUI extends Plugin {
1359
1448
  return actionsView;
1360
1449
  }
1361
1450
  /**
1362
- * Creates the {@link module:link/ui/linkformview~LinkFormView} instance.
1363
- */ _createFormView() {
1451
+ * Creates the {@link module:link/ui/linkformview~LinkFormView} instance.
1452
+ */ _createFormView() {
1364
1453
  const editor = this.editor;
1365
1454
  const linkCommand = editor.commands.get('link');
1366
1455
  const defaultProtocol = editor.config.get('link.defaultProtocol');
@@ -1395,9 +1484,9 @@ class LinkUI extends Plugin {
1395
1484
  return formView;
1396
1485
  }
1397
1486
  /**
1398
- * Creates a toolbar Link button. Clicking this button will show
1399
- * a {@link #_balloon} attached to the selection.
1400
- */ _createToolbarLinkButton() {
1487
+ * Creates a toolbar Link button. Clicking this button will show
1488
+ * a {@link #_balloon} attached to the selection.
1489
+ */ _createToolbarLinkButton() {
1401
1490
  const editor = this.editor;
1402
1491
  const linkCommand = editor.commands.get('link');
1403
1492
  editor.ui.componentFactory.add('link', ()=>{
@@ -1414,8 +1503,8 @@ class LinkUI extends Plugin {
1414
1503
  });
1415
1504
  }
1416
1505
  /**
1417
- * Creates a button for link command to use either in toolbar or in menu bar.
1418
- */ _createButton(ButtonClass) {
1506
+ * Creates a button for link command to use either in toolbar or in menu bar.
1507
+ */ _createButton(ButtonClass) {
1419
1508
  const editor = this.editor;
1420
1509
  const locale = editor.locale;
1421
1510
  const command = editor.commands.get('link');
@@ -1432,9 +1521,9 @@ class LinkUI extends Plugin {
1432
1521
  return view;
1433
1522
  }
1434
1523
  /**
1435
- * Attaches actions that control whether the balloon panel containing the
1436
- * {@link #formView} should be displayed.
1437
- */ _enableBalloonActivators() {
1524
+ * Attaches actions that control whether the balloon panel containing the
1525
+ * {@link #formView} should be displayed.
1526
+ */ _enableBalloonActivators() {
1438
1527
  const editor = this.editor;
1439
1528
  const viewDocument = editor.editing.view.document;
1440
1529
  // Handle click on view document and show panel when selection is placed inside the link element.
@@ -1456,9 +1545,9 @@ class LinkUI extends Plugin {
1456
1545
  });
1457
1546
  }
1458
1547
  /**
1459
- * Attaches actions that control whether the balloon panel containing the
1460
- * {@link #formView} is visible or not.
1461
- */ _enableUserBalloonInteractions() {
1548
+ * Attaches actions that control whether the balloon panel containing the
1549
+ * {@link #formView} is visible or not.
1550
+ */ _enableUserBalloonInteractions() {
1462
1551
  // Focus the form if the balloon is visible and the Tab key has been pressed.
1463
1552
  this.editor.keystrokes.set('Tab', (data, cancel)=>{
1464
1553
  if (this._areActionsVisible && !this.actionsView.focusTracker.isFocused) {
@@ -1489,10 +1578,10 @@ class LinkUI extends Plugin {
1489
1578
  });
1490
1579
  }
1491
1580
  /**
1492
- * Adds the {@link #actionsView} to the {@link #_balloon}.
1493
- *
1494
- * @internal
1495
- */ _addActionsView() {
1581
+ * Adds the {@link #actionsView} to the {@link #_balloon}.
1582
+ *
1583
+ * @internal
1584
+ */ _addActionsView() {
1496
1585
  if (!this.actionsView) {
1497
1586
  this._createViews();
1498
1587
  }
@@ -1505,8 +1594,8 @@ class LinkUI extends Plugin {
1505
1594
  });
1506
1595
  }
1507
1596
  /**
1508
- * Adds the {@link #formView} to the {@link #_balloon}.
1509
- */ _addFormView() {
1597
+ * Adds the {@link #formView} to the {@link #_balloon}.
1598
+ */ _addFormView() {
1510
1599
  if (!this.formView) {
1511
1600
  this._createViews();
1512
1601
  }
@@ -1535,12 +1624,12 @@ class LinkUI extends Plugin {
1535
1624
  this.formView.enableCssTransitions();
1536
1625
  }
1537
1626
  /**
1538
- * Closes the form view. Decides whether the balloon should be hidden completely or if the action view should be shown. This is
1539
- * decided upon the link command value (which has a value if the document selection is in the link).
1540
- *
1541
- * Additionally, if any {@link module:link/linkconfig~LinkConfig#decorators} are defined in the editor configuration, the state of
1542
- * switch buttons responsible for manual decorator handling is restored.
1543
- */ _closeFormView() {
1627
+ * Closes the form view. Decides whether the balloon should be hidden completely or if the action view should be shown. This is
1628
+ * decided upon the link command value (which has a value if the document selection is in the link).
1629
+ *
1630
+ * Additionally, if any {@link module:link/linkconfig~LinkConfig#decorators} are defined in the editor configuration, the state of
1631
+ * switch buttons responsible for manual decorator handling is restored.
1632
+ */ _closeFormView() {
1544
1633
  const linkCommand = this.editor.commands.get('link');
1545
1634
  // Restore manual decorator states to represent the current model state. This case is important to reset the switch buttons
1546
1635
  // when the user cancels the editing form.
@@ -1552,8 +1641,8 @@ class LinkUI extends Plugin {
1552
1641
  }
1553
1642
  }
1554
1643
  /**
1555
- * Removes the {@link #formView} from the {@link #_balloon}.
1556
- */ _removeFormView() {
1644
+ * Removes the {@link #formView} from the {@link #_balloon}.
1645
+ */ _removeFormView() {
1557
1646
  if (this._isFormInPanel) {
1558
1647
  // Blur the input element before removing it from DOM to prevent issues in some browsers.
1559
1648
  // See https://github.com/ckeditor/ckeditor5/issues/1501.
@@ -1568,10 +1657,10 @@ class LinkUI extends Plugin {
1568
1657
  }
1569
1658
  }
1570
1659
  /**
1571
- * Shows the correct UI type. It is either {@link #formView} or {@link #actionsView}.
1572
- *
1573
- * @internal
1574
- */ _showUI(forceVisible = false) {
1660
+ * Shows the correct UI type. It is either {@link #formView} or {@link #actionsView}.
1661
+ *
1662
+ * @internal
1663
+ */ _showUI(forceVisible = false) {
1575
1664
  if (!this.formView) {
1576
1665
  this._createViews();
1577
1666
  }
@@ -1602,10 +1691,10 @@ class LinkUI extends Plugin {
1602
1691
  this._startUpdatingUI();
1603
1692
  }
1604
1693
  /**
1605
- * Removes the {@link #formView} from the {@link #_balloon}.
1606
- *
1607
- * See {@link #_addFormView}, {@link #_addActionsView}.
1608
- */ _hideUI() {
1694
+ * Removes the {@link #formView} from the {@link #_balloon}.
1695
+ *
1696
+ * See {@link #_addFormView}, {@link #_addActionsView}.
1697
+ */ _hideUI() {
1609
1698
  if (!this._isUIInPanel) {
1610
1699
  return;
1611
1700
  }
@@ -1622,11 +1711,11 @@ class LinkUI extends Plugin {
1622
1711
  this._hideFakeVisualSelection();
1623
1712
  }
1624
1713
  /**
1625
- * Makes the UI react to the {@link module:ui/editorui/editorui~EditorUI#event:update} event to
1626
- * reposition itself when the editor UI should be refreshed.
1627
- *
1628
- * See: {@link #_hideUI} to learn when the UI stops reacting to the `update` event.
1629
- */ _startUpdatingUI() {
1714
+ * Makes the UI react to the {@link module:ui/editorui/editorui~EditorUI#event:update} event to
1715
+ * reposition itself when the editor UI should be refreshed.
1716
+ *
1717
+ * See: {@link #_hideUI} to learn when the UI stops reacting to the `update` event.
1718
+ */ _startUpdatingUI() {
1630
1719
  const editor = this.editor;
1631
1720
  const viewDocument = editor.editing.view.document;
1632
1721
  let prevSelectedLink = this._getSelectedLinkElement();
@@ -1662,40 +1751,40 @@ class LinkUI extends Plugin {
1662
1751
  this.listenTo(this._balloon, 'change:visibleView', update);
1663
1752
  }
1664
1753
  /**
1665
- * Returns `true` when {@link #formView} is in the {@link #_balloon}.
1666
- */ get _isFormInPanel() {
1754
+ * Returns `true` when {@link #formView} is in the {@link #_balloon}.
1755
+ */ get _isFormInPanel() {
1667
1756
  return !!this.formView && this._balloon.hasView(this.formView);
1668
1757
  }
1669
1758
  /**
1670
- * Returns `true` when {@link #actionsView} is in the {@link #_balloon}.
1671
- */ get _areActionsInPanel() {
1759
+ * Returns `true` when {@link #actionsView} is in the {@link #_balloon}.
1760
+ */ get _areActionsInPanel() {
1672
1761
  return !!this.actionsView && this._balloon.hasView(this.actionsView);
1673
1762
  }
1674
1763
  /**
1675
- * Returns `true` when {@link #actionsView} is in the {@link #_balloon} and it is
1676
- * currently visible.
1677
- */ get _areActionsVisible() {
1764
+ * Returns `true` when {@link #actionsView} is in the {@link #_balloon} and it is
1765
+ * currently visible.
1766
+ */ get _areActionsVisible() {
1678
1767
  return !!this.actionsView && this._balloon.visibleView === this.actionsView;
1679
1768
  }
1680
1769
  /**
1681
- * Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon}.
1682
- */ get _isUIInPanel() {
1770
+ * Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon}.
1771
+ */ get _isUIInPanel() {
1683
1772
  return this._isFormInPanel || this._areActionsInPanel;
1684
1773
  }
1685
1774
  /**
1686
- * Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon} and it is
1687
- * currently visible.
1688
- */ get _isUIVisible() {
1775
+ * Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon} and it is
1776
+ * currently visible.
1777
+ */ get _isUIVisible() {
1689
1778
  const visibleView = this._balloon.visibleView;
1690
1779
  return !!this.formView && visibleView == this.formView || this._areActionsVisible;
1691
1780
  }
1692
1781
  /**
1693
- * Returns positioning options for the {@link #_balloon}. They control the way the balloon is attached
1694
- * to the target element or selection.
1695
- *
1696
- * If the selection is collapsed and inside a link element, the panel will be attached to the
1697
- * entire link element. Otherwise, it will be attached to the selection.
1698
- */ _getBalloonPositionData() {
1782
+ * Returns positioning options for the {@link #_balloon}. They control the way the balloon is attached
1783
+ * to the target element or selection.
1784
+ *
1785
+ * If the selection is collapsed and inside a link element, the panel will be attached to the
1786
+ * entire link element. Otherwise, it will be attached to the selection.
1787
+ */ _getBalloonPositionData() {
1699
1788
  const view = this.editor.editing.view;
1700
1789
  const model = this.editor.model;
1701
1790
  const viewDocument = view.document;
@@ -1722,14 +1811,14 @@ class LinkUI extends Plugin {
1722
1811
  };
1723
1812
  }
1724
1813
  /**
1725
- * Returns the link {@link module:engine/view/attributeelement~AttributeElement} under
1726
- * the {@link module:engine/view/document~Document editing view's} selection or `null`
1727
- * if there is none.
1728
- *
1729
- * **Note**: For a non–collapsed selection, the link element is returned when **fully**
1730
- * selected and the **only** element within the selection boundaries, or when
1731
- * a linked widget is selected.
1732
- */ _getSelectedLinkElement() {
1814
+ * Returns the link {@link module:engine/view/attributeelement~AttributeElement} under
1815
+ * the {@link module:engine/view/document~Document editing view's} selection or `null`
1816
+ * if there is none.
1817
+ *
1818
+ * **Note**: For a non–collapsed selection, the link element is returned when **fully**
1819
+ * selected and the **only** element within the selection boundaries, or when
1820
+ * a linked widget is selected.
1821
+ */ _getSelectedLinkElement() {
1733
1822
  const view = this.editor.editing.view;
1734
1823
  const selection = view.document.selection;
1735
1824
  const selectedElement = selection.getSelectedElement();
@@ -1754,10 +1843,10 @@ class LinkUI extends Plugin {
1754
1843
  }
1755
1844
  }
1756
1845
  /**
1757
- * Displays a fake visual selection when the contextual balloon is displayed.
1758
- *
1759
- * This adds a 'link-ui' marker into the document that is rendered as a highlight on selected text fragment.
1760
- */ _showFakeVisualSelection() {
1846
+ * Displays a fake visual selection when the contextual balloon is displayed.
1847
+ *
1848
+ * This adds a 'link-ui' marker into the document that is rendered as a highlight on selected text fragment.
1849
+ */ _showFakeVisualSelection() {
1761
1850
  const model = this.editor.model;
1762
1851
  model.change((writer)=>{
1763
1852
  const range = model.document.selection.getFirstRange();
@@ -1786,8 +1875,8 @@ class LinkUI extends Plugin {
1786
1875
  });
1787
1876
  }
1788
1877
  /**
1789
- * Hides the fake visual selection created in {@link #_showFakeVisualSelection}.
1790
- */ _hideFakeVisualSelection() {
1878
+ * Hides the fake visual selection created in {@link #_showFakeVisualSelection}.
1879
+ */ _hideFakeVisualSelection() {
1791
1880
  const model = this.editor.model;
1792
1881
  if (model.markers.has(VISUAL_SELECTION_MARKER_NAME)) {
1793
1882
  model.change((writer)=>{
@@ -1795,15 +1884,6 @@ class LinkUI extends Plugin {
1795
1884
  });
1796
1885
  }
1797
1886
  }
1798
- constructor(){
1799
- super(...arguments);
1800
- /**
1801
- * The actions view displayed inside of the balloon.
1802
- */ this.actionsView = null;
1803
- /**
1804
- * The form view displayed inside the balloon.
1805
- */ this.formView = null;
1806
- }
1807
1887
  }
1808
1888
  /**
1809
1889
  * Returns a link element if there's one among the ancestors of the provided `Position`.
@@ -1851,23 +1931,25 @@ const URL_REG_EXP = new RegExp(// Group 1: Line start or after a space.
1851
1931
  '((?![-_])(?:[-_a-z0-9\\u00a1-\\uffff]{1,63}\\.))+' + // TLD identifier name.
1852
1932
  '(?:[a-z\\u00a1-\\uffff]{2,63})' + ')' + ')$', 'i');
1853
1933
  const URL_GROUP_IN_MATCH = 2;
1854
- class AutoLink extends Plugin {
1934
+ /**
1935
+ * The autolink plugin.
1936
+ */ class AutoLink extends Plugin {
1855
1937
  /**
1856
- * @inheritDoc
1857
- */ static get requires() {
1938
+ * @inheritDoc
1939
+ */ static get requires() {
1858
1940
  return [
1859
1941
  Delete,
1860
1942
  LinkEditing
1861
1943
  ];
1862
1944
  }
1863
1945
  /**
1864
- * @inheritDoc
1865
- */ static get pluginName() {
1946
+ * @inheritDoc
1947
+ */ static get pluginName() {
1866
1948
  return 'AutoLink';
1867
1949
  }
1868
1950
  /**
1869
- * @inheritDoc
1870
- */ init() {
1951
+ * @inheritDoc
1952
+ */ init() {
1871
1953
  const editor = this.editor;
1872
1954
  const selection = editor.model.document.selection;
1873
1955
  selection.on('change:range', ()=>{
@@ -1877,17 +1959,17 @@ class AutoLink extends Plugin {
1877
1959
  this._enableTypingHandling();
1878
1960
  }
1879
1961
  /**
1880
- * @inheritDoc
1881
- */ afterInit() {
1962
+ * @inheritDoc
1963
+ */ afterInit() {
1882
1964
  this._enableEnterHandling();
1883
1965
  this._enableShiftEnterHandling();
1884
1966
  this._enablePasteLinking();
1885
1967
  }
1886
1968
  /**
1887
- * For given position, returns a range that includes the whole link that contains the position.
1888
- *
1889
- * If position is not inside a link, returns `null`.
1890
- */ _expandLinkRange(model, position) {
1969
+ * For given position, returns a range that includes the whole link that contains the position.
1970
+ *
1971
+ * If position is not inside a link, returns `null`.
1972
+ */ _expandLinkRange(model, position) {
1891
1973
  if (position.textNode && position.textNode.hasAttribute('linkHref')) {
1892
1974
  return findAttributeRange(position, 'linkHref', position.textNode.getAttribute('linkHref'), model);
1893
1975
  } else {
@@ -1895,8 +1977,8 @@ class AutoLink extends Plugin {
1895
1977
  }
1896
1978
  }
1897
1979
  /**
1898
- * Extends the document selection to includes all links that intersects with given `selectedRange`.
1899
- */ _selectEntireLinks(writer, selectedRange) {
1980
+ * Extends the document selection to includes all links that intersects with given `selectedRange`.
1981
+ */ _selectEntireLinks(writer, selectedRange) {
1900
1982
  const editor = this.editor;
1901
1983
  const model = editor.model;
1902
1984
  const selection = model.document.selection;
@@ -1912,8 +1994,8 @@ class AutoLink extends Plugin {
1912
1994
  }
1913
1995
  }
1914
1996
  /**
1915
- * Enables autolinking on pasting a URL when some content is selected.
1916
- */ _enablePasteLinking() {
1997
+ * Enables autolinking on pasting a URL when some content is selected.
1998
+ */ _enablePasteLinking() {
1917
1999
  const editor = this.editor;
1918
2000
  const model = editor.model;
1919
2001
  const selection = model.document.selection;
@@ -1948,8 +2030,8 @@ class AutoLink extends Plugin {
1948
2030
  });
1949
2031
  }
1950
2032
  /**
1951
- * Enables autolinking on typing.
1952
- */ _enableTypingHandling() {
2033
+ * Enables autolinking on typing.
2034
+ */ _enableTypingHandling() {
1953
2035
  const editor = this.editor;
1954
2036
  const watcher = new TextWatcher(editor.model, (text)=>{
1955
2037
  // 1. Detect <kbd>Space</kbd> after a text with a potential link.
@@ -1977,8 +2059,8 @@ class AutoLink extends Plugin {
1977
2059
  watcher.bind('isEnabled').to(this);
1978
2060
  }
1979
2061
  /**
1980
- * Enables autolinking on the <kbd>Enter</kbd> key.
1981
- */ _enableEnterHandling() {
2062
+ * Enables autolinking on the <kbd>Enter</kbd> key.
2063
+ */ _enableEnterHandling() {
1982
2064
  const editor = this.editor;
1983
2065
  const model = editor.model;
1984
2066
  const enterCommand = editor.commands.get('enter');
@@ -1995,8 +2077,8 @@ class AutoLink extends Plugin {
1995
2077
  });
1996
2078
  }
1997
2079
  /**
1998
- * Enables autolinking on the <kbd>Shift</kbd>+<kbd>Enter</kbd> keyboard shortcut.
1999
- */ _enableShiftEnterHandling() {
2080
+ * Enables autolinking on the <kbd>Shift</kbd>+<kbd>Enter</kbd> keyboard shortcut.
2081
+ */ _enableShiftEnterHandling() {
2000
2082
  const editor = this.editor;
2001
2083
  const model = editor.model;
2002
2084
  const shiftEnterCommand = editor.commands.get('shiftEnter');
@@ -2010,8 +2092,8 @@ class AutoLink extends Plugin {
2010
2092
  });
2011
2093
  }
2012
2094
  /**
2013
- * Checks if the passed range contains a linkable text.
2014
- */ _checkAndApplyAutoLinkOnRange(rangeToCheck) {
2095
+ * Checks if the passed range contains a linkable text.
2096
+ */ _checkAndApplyAutoLinkOnRange(rangeToCheck) {
2015
2097
  const model = this.editor.model;
2016
2098
  const { text, range } = getLastTextLine(rangeToCheck, model);
2017
2099
  const url = getUrlAtTextEnd(text);
@@ -2021,11 +2103,11 @@ class AutoLink extends Plugin {
2021
2103
  }
2022
2104
  }
2023
2105
  /**
2024
- * Applies a link on a given range if the link should be applied.
2025
- *
2026
- * @param url The URL to link.
2027
- * @param range The text range to apply the link attribute to.
2028
- */ _applyAutoLink(url, range) {
2106
+ * Applies a link on a given range if the link should be applied.
2107
+ *
2108
+ * @param url The URL to link.
2109
+ * @param range The text range to apply the link attribute to.
2110
+ */ _applyAutoLink(url, range) {
2029
2111
  const model = this.editor.model;
2030
2112
  const defaultProtocol = this.editor.config.get('link.defaultProtocol');
2031
2113
  const fullUrl = addLinkProtocolIfApplicable(url, defaultProtocol);
@@ -2035,11 +2117,11 @@ class AutoLink extends Plugin {
2035
2117
  this._persistAutoLink(fullUrl, range);
2036
2118
  }
2037
2119
  /**
2038
- * Enqueues autolink changes in the model.
2039
- *
2040
- * @param url The URL to link.
2041
- * @param range The text range to apply the link attribute to.
2042
- */ _persistAutoLink(url, range) {
2120
+ * Enqueues autolink changes in the model.
2121
+ *
2122
+ * @param url The URL to link.
2123
+ * @param range The text range to apply the link attribute to.
2124
+ */ _persistAutoLink(url, range) {
2043
2125
  const model = this.editor.model;
2044
2126
  const deletePlugin = this.editor.plugins.get('Delete');
2045
2127
  // Enqueue change to make undo step.
@@ -2067,10 +2149,15 @@ function linkIsAlreadySet(range) {
2067
2149
  return !!item && item.hasAttribute('linkHref');
2068
2150
  }
2069
2151
 
2070
- class Link extends Plugin {
2152
+ /**
2153
+ * The link plugin.
2154
+ *
2155
+ * This is a "glue" plugin that loads the {@link module:link/linkediting~LinkEditing link editing feature}
2156
+ * and {@link module:link/linkui~LinkUI link UI feature}.
2157
+ */ class Link extends Plugin {
2071
2158
  /**
2072
- * @inheritDoc
2073
- */ static get requires() {
2159
+ * @inheritDoc
2160
+ */ static get requires() {
2074
2161
  return [
2075
2162
  LinkEditing,
2076
2163
  LinkUI,
@@ -2078,16 +2165,21 @@ class Link extends Plugin {
2078
2165
  ];
2079
2166
  }
2080
2167
  /**
2081
- * @inheritDoc
2082
- */ static get pluginName() {
2168
+ * @inheritDoc
2169
+ */ static get pluginName() {
2083
2170
  return 'Link';
2084
2171
  }
2085
2172
  }
2086
2173
 
2087
- class LinkImageEditing extends Plugin {
2174
+ /**
2175
+ * The link image engine feature.
2176
+ *
2177
+ * It accepts the `linkHref="url"` attribute in the model for the {@link module:image/image~Image `<imageBlock>`} element
2178
+ * which allows linking images.
2179
+ */ class LinkImageEditing extends Plugin {
2088
2180
  /**
2089
- * @inheritDoc
2090
- */ static get requires() {
2181
+ * @inheritDoc
2182
+ */ static get requires() {
2091
2183
  return [
2092
2184
  'ImageEditing',
2093
2185
  'ImageUtils',
@@ -2095,13 +2187,13 @@ class LinkImageEditing extends Plugin {
2095
2187
  ];
2096
2188
  }
2097
2189
  /**
2098
- * @inheritDoc
2099
- */ static get pluginName() {
2190
+ * @inheritDoc
2191
+ */ static get pluginName() {
2100
2192
  return 'LinkImageEditing';
2101
2193
  }
2102
2194
  /**
2103
- * @inheritDoc
2104
- */ afterInit() {
2195
+ * @inheritDoc
2196
+ */ afterInit() {
2105
2197
  const editor = this.editor;
2106
2198
  const schema = editor.model.schema;
2107
2199
  if (editor.plugins.has('ImageBlockEditing')) {
@@ -2118,9 +2210,9 @@ class LinkImageEditing extends Plugin {
2118
2210
  this._enableManualDecorators();
2119
2211
  }
2120
2212
  /**
2121
- * Processes {@link module:link/linkconfig~LinkDecoratorAutomaticDefinition automatic decorators} definitions and
2122
- * attaches proper converters that will work when linking an image.`
2123
- */ _enableAutomaticDecorators() {
2213
+ * Processes {@link module:link/linkconfig~LinkDecoratorAutomaticDefinition automatic decorators} definitions and
2214
+ * attaches proper converters that will work when linking an image.`
2215
+ */ _enableAutomaticDecorators() {
2124
2216
  const editor = this.editor;
2125
2217
  const command = editor.commands.get('link');
2126
2218
  const automaticDecorators = command.automaticDecorators;
@@ -2129,9 +2221,9 @@ class LinkImageEditing extends Plugin {
2129
2221
  }
2130
2222
  }
2131
2223
  /**
2132
- * Processes transformed {@link module:link/utils/manualdecorator~ManualDecorator} instances and attaches proper converters
2133
- * that will work when linking an image.
2134
- */ _enableManualDecorators() {
2224
+ * Processes transformed {@link module:link/utils/manualdecorator~ManualDecorator} instances and attaches proper converters
2225
+ * that will work when linking an image.
2226
+ */ _enableManualDecorators() {
2135
2227
  const editor = this.editor;
2136
2228
  const command = editor.commands.get('link');
2137
2229
  for (const decorator of command.manualDecorators){
@@ -2324,10 +2416,15 @@ class LinkImageEditing extends Plugin {
2324
2416
  };
2325
2417
  }
2326
2418
 
2327
- class LinkImageUI extends Plugin {
2419
+ /**
2420
+ * The link image UI plugin.
2421
+ *
2422
+ * This plugin provides the `'linkImage'` button that can be displayed in the {@link module:image/imagetoolbar~ImageToolbar}.
2423
+ * It can be used to wrap images in links.
2424
+ */ class LinkImageUI extends Plugin {
2328
2425
  /**
2329
- * @inheritDoc
2330
- */ static get requires() {
2426
+ * @inheritDoc
2427
+ */ static get requires() {
2331
2428
  return [
2332
2429
  LinkEditing,
2333
2430
  LinkUI,
@@ -2335,13 +2432,13 @@ class LinkImageUI extends Plugin {
2335
2432
  ];
2336
2433
  }
2337
2434
  /**
2338
- * @inheritDoc
2339
- */ static get pluginName() {
2435
+ * @inheritDoc
2436
+ */ static get pluginName() {
2340
2437
  return 'LinkImageUI';
2341
2438
  }
2342
2439
  /**
2343
- * @inheritDoc
2344
- */ init() {
2440
+ * @inheritDoc
2441
+ */ init() {
2345
2442
  const editor = this.editor;
2346
2443
  const viewDocument = editor.editing.view.document;
2347
2444
  this.listenTo(viewDocument, 'click', (evt, data)=>{
@@ -2358,12 +2455,12 @@ class LinkImageUI extends Plugin {
2358
2455
  this._createToolbarLinkImageButton();
2359
2456
  }
2360
2457
  /**
2361
- * Creates a `LinkImageUI` button view.
2362
- *
2363
- * Clicking this button shows a {@link module:link/linkui~LinkUI#_balloon} attached to the selection.
2364
- * When an image is already linked, the view shows {@link module:link/linkui~LinkUI#actionsView} or
2365
- * {@link module:link/linkui~LinkUI#formView} if it is not.
2366
- */ _createToolbarLinkImageButton() {
2458
+ * Creates a `LinkImageUI` button view.
2459
+ *
2460
+ * Clicking this button shows a {@link module:link/linkui~LinkUI#_balloon} attached to the selection.
2461
+ * When an image is already linked, the view shows {@link module:link/linkui~LinkUI#actionsView} or
2462
+ * {@link module:link/linkui~LinkUI#formView} if it is not.
2463
+ */ _createToolbarLinkImageButton() {
2367
2464
  const editor = this.editor;
2368
2465
  const t = editor.t;
2369
2466
  editor.ui.componentFactory.add('linkImage', (locale)=>{
@@ -2393,27 +2490,32 @@ class LinkImageUI extends Plugin {
2393
2490
  });
2394
2491
  }
2395
2492
  /**
2396
- * Returns true if a linked image (either block or inline) is the only selected element
2397
- * in the model document.
2398
- */ _isSelectedLinkedImage(selection) {
2493
+ * Returns true if a linked image (either block or inline) is the only selected element
2494
+ * in the model document.
2495
+ */ _isSelectedLinkedImage(selection) {
2399
2496
  const selectedModelElement = selection.getSelectedElement();
2400
2497
  const imageUtils = this.editor.plugins.get('ImageUtils');
2401
2498
  return imageUtils.isImage(selectedModelElement) && selectedModelElement.hasAttribute('linkHref');
2402
2499
  }
2403
2500
  }
2404
2501
 
2405
- class LinkImage extends Plugin {
2502
+ /**
2503
+ * The `LinkImage` plugin.
2504
+ *
2505
+ * This is a "glue" plugin that loads the {@link module:link/linkimageediting~LinkImageEditing link image editing feature}
2506
+ * and {@link module:link/linkimageui~LinkImageUI link image UI feature}.
2507
+ */ class LinkImage extends Plugin {
2406
2508
  /**
2407
- * @inheritDoc
2408
- */ static get requires() {
2509
+ * @inheritDoc
2510
+ */ static get requires() {
2409
2511
  return [
2410
2512
  LinkImageEditing,
2411
2513
  LinkImageUI
2412
2514
  ];
2413
2515
  }
2414
2516
  /**
2415
- * @inheritDoc
2416
- */ static get pluginName() {
2517
+ * @inheritDoc
2518
+ */ static get pluginName() {
2417
2519
  return 'LinkImage';
2418
2520
  }
2419
2521
  }