@ckeditor/ckeditor5-link 0.0.0-nightly-20240604.1 → 0.0.0-nightly-20240605.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/README.md +0 -6
- package/build/link.js +1 -1
- package/dist/index.js +531 -634
- package/dist/index.js.map +1 -1
- package/dist/types/utils/manualdecorator.d.ts +1 -1
- package/package.json +3 -3
- package/src/ui/linkformview.js +0 -1
- package/src/utils/manualdecorator.d.ts +1 -1
- package/src/utils/manualdecorator.js +1 -1
package/dist/index.js
CHANGED
|
@@ -5,31 +5,24 @@
|
|
|
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,
|
|
8
|
+
import { toMap, first, Collection, 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,
|
|
11
|
+
import { View, submitHandler, LabeledFieldView, createLabeledInputText, ButtonView, SwitchButtonView, ViewCollection, FocusCycler, 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
|
-
|
|
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();
|
|
14
|
+
class AutomaticDecorators {
|
|
22
15
|
/**
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
* Gives information about the number of decorators stored in the {@link module:link/utils/automaticdecorators~AutomaticDecorators}
|
|
17
|
+
* instance.
|
|
18
|
+
*/ get length() {
|
|
26
19
|
return this._definitions.size;
|
|
27
20
|
}
|
|
28
21
|
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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) {
|
|
33
26
|
if (Array.isArray(item)) {
|
|
34
27
|
item.forEach((item)=>this._definitions.add(item));
|
|
35
28
|
} else {
|
|
@@ -37,10 +30,10 @@ import { isWidget } from '@ckeditor/ckeditor5-widget/dist/index.js';
|
|
|
37
30
|
}
|
|
38
31
|
}
|
|
39
32
|
/**
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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() {
|
|
44
37
|
return (dispatcher)=>{
|
|
45
38
|
dispatcher.on('attribute:linkHref', (evt, data, conversionApi)=>{
|
|
46
39
|
// There is only test as this behavior decorates links and
|
|
@@ -83,11 +76,11 @@ import { isWidget } from '@ckeditor/ckeditor5-widget/dist/index.js';
|
|
|
83
76
|
};
|
|
84
77
|
}
|
|
85
78
|
/**
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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() {
|
|
91
84
|
return (dispatcher)=>{
|
|
92
85
|
dispatcher.on('attribute:linkHref:imageBlock', (evt, data, { writer, mapper })=>{
|
|
93
86
|
const viewFigure = mapper.toViewElement(data.item);
|
|
@@ -129,6 +122,12 @@ import { isWidget } from '@ckeditor/ckeditor5-widget/dist/index.js';
|
|
|
129
122
|
});
|
|
130
123
|
};
|
|
131
124
|
}
|
|
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
|
+
}
|
|
132
131
|
}
|
|
133
132
|
|
|
134
133
|
const ATTRIBUTE_WHITESPACES = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g; // eslint-disable-line no-control-regex
|
|
@@ -256,29 +255,17 @@ const DEFAULT_LINK_PROTOCOLS = [
|
|
|
256
255
|
window.open(link, '_blank', 'noopener');
|
|
257
256
|
}
|
|
258
257
|
|
|
259
|
-
|
|
260
|
-
* The link command. It is used by the {@link module:link/link~Link link feature}.
|
|
261
|
-
*/ class LinkCommand extends Command {
|
|
258
|
+
class LinkCommand extends Command {
|
|
262
259
|
/**
|
|
263
|
-
|
|
264
|
-
|
|
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() {
|
|
260
|
+
* Synchronizes the state of {@link #manualDecorators} with the currently present elements in the model.
|
|
261
|
+
*/ restoreManualDecoratorStates() {
|
|
275
262
|
for (const manualDecorator of this.manualDecorators){
|
|
276
263
|
manualDecorator.value = this._getDecoratorStateFromModel(manualDecorator.id);
|
|
277
264
|
}
|
|
278
265
|
}
|
|
279
266
|
/**
|
|
280
|
-
|
|
281
|
-
|
|
267
|
+
* @inheritDoc
|
|
268
|
+
*/ refresh() {
|
|
282
269
|
const model = this.editor.model;
|
|
283
270
|
const selection = model.document.selection;
|
|
284
271
|
const selectedElement = selection.getSelectedElement() || first(selection.getSelectedBlocks());
|
|
@@ -296,70 +283,70 @@ const DEFAULT_LINK_PROTOCOLS = [
|
|
|
296
283
|
}
|
|
297
284
|
}
|
|
298
285
|
/**
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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 = {}) {
|
|
363
350
|
const model = this.editor.model;
|
|
364
351
|
const selection = model.document.selection;
|
|
365
352
|
// Stores information about manual decorators to turn them on/off when command is applied.
|
|
@@ -455,11 +442,11 @@ const DEFAULT_LINK_PROTOCOLS = [
|
|
|
455
442
|
});
|
|
456
443
|
}
|
|
457
444
|
/**
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
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) {
|
|
463
450
|
const model = this.editor.model;
|
|
464
451
|
const selection = model.document.selection;
|
|
465
452
|
const selectedElement = selection.getSelectedElement();
|
|
@@ -471,11 +458,11 @@ const DEFAULT_LINK_PROTOCOLS = [
|
|
|
471
458
|
return selection.getAttribute(decoratorName);
|
|
472
459
|
}
|
|
473
460
|
/**
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
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) {
|
|
479
466
|
for (const allowedRange of allowedRanges){
|
|
480
467
|
// A range is inside an element that will have the `linkHref` attribute. Do not modify its nodes.
|
|
481
468
|
if (allowedRange.containsRange(range)) {
|
|
@@ -485,18 +472,31 @@ const DEFAULT_LINK_PROTOCOLS = [
|
|
|
485
472
|
return true;
|
|
486
473
|
}
|
|
487
474
|
/**
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
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) {
|
|
495
482
|
const text = writer.createText(href, {
|
|
496
483
|
linkHref: href
|
|
497
484
|
});
|
|
498
485
|
return model.insertContent(text, range);
|
|
499
486
|
}
|
|
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,12 +516,10 @@ function extractTextFromSelection(selection) {
|
|
|
516
516
|
}
|
|
517
517
|
}
|
|
518
518
|
|
|
519
|
-
|
|
520
|
-
* The unlink command. It is used by the {@link module:link/link~Link link plugin}.
|
|
521
|
-
*/ class UnlinkCommand extends Command {
|
|
519
|
+
class UnlinkCommand extends Command {
|
|
522
520
|
/**
|
|
523
|
-
|
|
524
|
-
|
|
521
|
+
* @inheritDoc
|
|
522
|
+
*/ refresh() {
|
|
525
523
|
const model = this.editor.model;
|
|
526
524
|
const selection = model.document.selection;
|
|
527
525
|
const selectedElement = selection.getSelectedElement();
|
|
@@ -534,18 +532,18 @@ function extractTextFromSelection(selection) {
|
|
|
534
532
|
}
|
|
535
533
|
}
|
|
536
534
|
/**
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
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() {
|
|
549
547
|
const editor = this.editor;
|
|
550
548
|
const model = this.editor.model;
|
|
551
549
|
const selection = model.document.selection;
|
|
@@ -569,42 +567,28 @@ function extractTextFromSelection(selection) {
|
|
|
569
567
|
}
|
|
570
568
|
}
|
|
571
569
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
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 }){
|
|
570
|
+
class ManualDecorator extends 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 }){
|
|
608
592
|
super();
|
|
609
593
|
this.id = id;
|
|
610
594
|
this.set('value', undefined);
|
|
@@ -614,37 +598,21 @@ function extractTextFromSelection(selection) {
|
|
|
614
598
|
this.classes = classes;
|
|
615
599
|
this.styles = styles;
|
|
616
600
|
}
|
|
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
|
-
}
|
|
628
601
|
}
|
|
629
602
|
|
|
630
603
|
const HIGHLIGHT_CLASS = 'ck-link_selected';
|
|
631
604
|
const DECORATOR_AUTOMATIC = 'automatic';
|
|
632
605
|
const DECORATOR_MANUAL = 'manual';
|
|
633
606
|
const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
|
|
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 {
|
|
607
|
+
class LinkEditing extends Plugin {
|
|
640
608
|
/**
|
|
641
|
-
|
|
642
|
-
|
|
609
|
+
* @inheritDoc
|
|
610
|
+
*/ static get pluginName() {
|
|
643
611
|
return 'LinkEditing';
|
|
644
612
|
}
|
|
645
613
|
/**
|
|
646
|
-
|
|
647
|
-
|
|
614
|
+
* @inheritDoc
|
|
615
|
+
*/ static get requires() {
|
|
648
616
|
// Clipboard is required for handling cut and paste events while typing over the link.
|
|
649
617
|
return [
|
|
650
618
|
TwoStepCaretMovement,
|
|
@@ -653,17 +621,8 @@ const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
|
|
|
653
621
|
];
|
|
654
622
|
}
|
|
655
623
|
/**
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
super(editor);
|
|
659
|
-
editor.config.define('link', {
|
|
660
|
-
allowCreatingEmptyLinks: false,
|
|
661
|
-
addTargetToExternalLinks: false
|
|
662
|
-
});
|
|
663
|
-
}
|
|
664
|
-
/**
|
|
665
|
-
* @inheritDoc
|
|
666
|
-
*/ init() {
|
|
624
|
+
* @inheritDoc
|
|
625
|
+
*/ init() {
|
|
667
626
|
const editor = this.editor;
|
|
668
627
|
const allowedProtocols = this.editor.config.get('link.allowedProtocols');
|
|
669
628
|
// Allow link attribute on all inline nodes.
|
|
@@ -711,14 +670,14 @@ const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
|
|
|
711
670
|
this._enableClipboardIntegration();
|
|
712
671
|
}
|
|
713
672
|
/**
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
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) {
|
|
722
681
|
const editor = this.editor;
|
|
723
682
|
// Store automatic decorators in the command instance as we do the same with manual decorators.
|
|
724
683
|
// Thanks to that, `LinkImageEditing` plugin can re-use the same definitions.
|
|
@@ -742,14 +701,14 @@ const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
|
|
|
742
701
|
}
|
|
743
702
|
}
|
|
744
703
|
/**
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
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) {
|
|
753
712
|
if (!manualDecoratorDefinitions.length) {
|
|
754
713
|
return;
|
|
755
714
|
}
|
|
@@ -797,9 +756,9 @@ const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
|
|
|
797
756
|
});
|
|
798
757
|
}
|
|
799
758
|
/**
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
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() {
|
|
803
762
|
const editor = this.editor;
|
|
804
763
|
const view = editor.editing.view;
|
|
805
764
|
const viewDocument = view.document;
|
|
@@ -838,10 +797,10 @@ const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
|
|
|
838
797
|
});
|
|
839
798
|
}
|
|
840
799
|
/**
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
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() {
|
|
845
804
|
const editor = this.editor;
|
|
846
805
|
const model = editor.model;
|
|
847
806
|
const selection = model.document.selection;
|
|
@@ -855,8 +814,8 @@ const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
|
|
|
855
814
|
});
|
|
856
815
|
}
|
|
857
816
|
/**
|
|
858
|
-
|
|
859
|
-
|
|
817
|
+
* Enables URL fixing on pasting.
|
|
818
|
+
*/ _enableClipboardIntegration() {
|
|
860
819
|
const editor = this.editor;
|
|
861
820
|
const model = editor.model;
|
|
862
821
|
const defaultProtocol = this.editor.config.get('link.defaultProtocol');
|
|
@@ -875,6 +834,15 @@ const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
|
|
|
875
834
|
});
|
|
876
835
|
});
|
|
877
836
|
}
|
|
837
|
+
/**
|
|
838
|
+
* @inheritDoc
|
|
839
|
+
*/ constructor(editor){
|
|
840
|
+
super(editor);
|
|
841
|
+
editor.config.define('link', {
|
|
842
|
+
allowCreatingEmptyLinks: false,
|
|
843
|
+
addTargetToExternalLinks: false
|
|
844
|
+
});
|
|
845
|
+
}
|
|
878
846
|
}
|
|
879
847
|
/**
|
|
880
848
|
* Make the selection free of link-related model attributes.
|
|
@@ -893,105 +861,22 @@ const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
|
|
|
893
861
|
return textAttributes.filter((attribute)=>attribute.startsWith('link'));
|
|
894
862
|
}
|
|
895
863
|
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
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() {
|
|
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() {
|
|
987
872
|
return Array.from(this._manualDecoratorSwitches).reduce((accumulator, switchButton)=>{
|
|
988
873
|
accumulator[switchButton.name] = switchButton.isOn;
|
|
989
874
|
return accumulator;
|
|
990
875
|
}, {});
|
|
991
876
|
}
|
|
992
877
|
/**
|
|
993
|
-
|
|
994
|
-
|
|
878
|
+
* @inheritDoc
|
|
879
|
+
*/ render() {
|
|
995
880
|
super.render();
|
|
996
881
|
submitHandler({
|
|
997
882
|
view: this
|
|
@@ -1012,20 +897,20 @@ const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
|
|
|
1012
897
|
this.keystrokes.listenTo(this.element);
|
|
1013
898
|
}
|
|
1014
899
|
/**
|
|
1015
|
-
|
|
1016
|
-
|
|
900
|
+
* @inheritDoc
|
|
901
|
+
*/ destroy() {
|
|
1017
902
|
super.destroy();
|
|
1018
903
|
this.focusTracker.destroy();
|
|
1019
904
|
this.keystrokes.destroy();
|
|
1020
905
|
}
|
|
1021
906
|
/**
|
|
1022
|
-
|
|
1023
|
-
|
|
907
|
+
* Focuses the fist {@link #_focusables} in the form.
|
|
908
|
+
*/ focus() {
|
|
1024
909
|
this._focusCycler.focusFirst();
|
|
1025
910
|
}
|
|
1026
911
|
/**
|
|
1027
|
-
|
|
1028
|
-
|
|
912
|
+
* Validates the form and returns `false` when some fields are invalid.
|
|
913
|
+
*/ isValid() {
|
|
1029
914
|
this.resetFormStatus();
|
|
1030
915
|
for (const validator of this._validators){
|
|
1031
916
|
const errorText = validator(this);
|
|
@@ -1039,33 +924,32 @@ const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
|
|
|
1039
924
|
return true;
|
|
1040
925
|
}
|
|
1041
926
|
/**
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
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() {
|
|
1047
932
|
this.urlInputView.errorText = null;
|
|
1048
933
|
}
|
|
1049
934
|
/**
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
935
|
+
* Creates a labeled input view.
|
|
936
|
+
*
|
|
937
|
+
* @returns Labeled field view instance.
|
|
938
|
+
*/ _createUrlInput() {
|
|
1054
939
|
const t = this.locale.t;
|
|
1055
940
|
const labeledInput = new LabeledFieldView(this.locale, createLabeledInputText);
|
|
1056
|
-
labeledInput.fieldView.inputMode = 'url';
|
|
1057
941
|
labeledInput.label = t('Link URL');
|
|
1058
942
|
return labeledInput;
|
|
1059
943
|
}
|
|
1060
944
|
/**
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
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) {
|
|
1069
953
|
const button = new ButtonView(this.locale);
|
|
1070
954
|
button.set({
|
|
1071
955
|
label,
|
|
@@ -1083,12 +967,12 @@ const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
|
|
|
1083
967
|
return button;
|
|
1084
968
|
}
|
|
1085
969
|
/**
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
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) {
|
|
1092
976
|
const switches = this.createCollection();
|
|
1093
977
|
for (const manualDecorator of linkCommand.manualDecorators){
|
|
1094
978
|
const switchButton = new SwitchButtonView(this.locale);
|
|
@@ -1111,16 +995,16 @@ const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
|
|
|
1111
995
|
return switches;
|
|
1112
996
|
}
|
|
1113
997
|
/**
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
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) {
|
|
1124
1008
|
const children = this.createCollection();
|
|
1125
1009
|
children.add(this.urlInputView);
|
|
1126
1010
|
if (manualDecorators.length) {
|
|
@@ -1154,89 +1038,81 @@ const EXTERNAL_LINKS_REGEXP = /^(https?:)?\/\//;
|
|
|
1154
1038
|
return children;
|
|
1155
1039
|
}
|
|
1156
1040
|
/**
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
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() {
|
|
1162
1046
|
const { element } = this.urlInputView.fieldView;
|
|
1163
1047
|
if (!element) {
|
|
1164
1048
|
return null;
|
|
1165
1049
|
}
|
|
1166
1050
|
return element.value.trim();
|
|
1167
1051
|
}
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
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>";
|
|
1171
|
-
|
|
1172
|
-
/**
|
|
1173
|
-
* The link actions view class. This view displays the link preview, allows
|
|
1174
|
-
* unlinking or editing the link.
|
|
1175
|
-
*/ class LinkActionsView extends View {
|
|
1176
|
-
/**
|
|
1177
|
-
* Tracks information about DOM focus in the actions.
|
|
1178
|
-
*/ focusTracker = new FocusTracker();
|
|
1179
|
-
/**
|
|
1180
|
-
* An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
|
|
1181
|
-
*/ keystrokes = new KeystrokeHandler();
|
|
1182
1052
|
/**
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
/**
|
|
1192
|
-
* A collection of views that can be focused in the view.
|
|
1193
|
-
*/ _focusables = new ViewCollection();
|
|
1194
|
-
/**
|
|
1195
|
-
* Helps cycling over {@link #_focusables} in the view.
|
|
1196
|
-
*/ _focusCycler;
|
|
1197
|
-
_linkConfig;
|
|
1198
|
-
/**
|
|
1199
|
-
* @inheritDoc
|
|
1200
|
-
*/ constructor(locale, linkConfig = {}){
|
|
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){
|
|
1201
1061
|
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();
|
|
1202
1071
|
const t = locale.t;
|
|
1203
|
-
this.
|
|
1204
|
-
this.
|
|
1205
|
-
this.
|
|
1206
|
-
this.
|
|
1207
|
-
this.
|
|
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);
|
|
1208
1079
|
this._focusCycler = new FocusCycler({
|
|
1209
1080
|
focusables: this._focusables,
|
|
1210
1081
|
focusTracker: this.focusTracker,
|
|
1211
1082
|
keystrokeHandler: this.keystrokes,
|
|
1212
1083
|
actions: {
|
|
1213
|
-
// Navigate fields backwards using the Shift + Tab keystroke.
|
|
1084
|
+
// Navigate form fields backwards using the Shift + Tab keystroke.
|
|
1214
1085
|
focusPrevious: 'shift + tab',
|
|
1215
|
-
// Navigate fields forwards using the Tab key.
|
|
1086
|
+
// Navigate form fields forwards using the Tab key.
|
|
1216
1087
|
focusNext: 'tab'
|
|
1217
1088
|
}
|
|
1218
1089
|
});
|
|
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
|
+
}
|
|
1219
1098
|
this.setTemplate({
|
|
1220
|
-
tag: '
|
|
1099
|
+
tag: 'form',
|
|
1221
1100
|
attributes: {
|
|
1222
|
-
class:
|
|
1223
|
-
'ck',
|
|
1224
|
-
'ck-link-actions',
|
|
1225
|
-
'ck-responsive-form'
|
|
1226
|
-
],
|
|
1101
|
+
class: classList,
|
|
1227
1102
|
// https://github.com/ckeditor/ckeditor5-link/issues/90
|
|
1228
1103
|
tabindex: '-1'
|
|
1229
1104
|
},
|
|
1230
|
-
children:
|
|
1231
|
-
this.previewButtonView,
|
|
1232
|
-
this.editButtonView,
|
|
1233
|
-
this.unlinkButtonView
|
|
1234
|
-
]
|
|
1105
|
+
children: this.children
|
|
1235
1106
|
});
|
|
1236
1107
|
}
|
|
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 {
|
|
1237
1113
|
/**
|
|
1238
|
-
|
|
1239
|
-
|
|
1114
|
+
* @inheritDoc
|
|
1115
|
+
*/ render() {
|
|
1240
1116
|
super.render();
|
|
1241
1117
|
const childViews = [
|
|
1242
1118
|
this.previewButtonView,
|
|
@@ -1253,25 +1129,25 @@ var unlinkIcon = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\
|
|
|
1253
1129
|
this.keystrokes.listenTo(this.element);
|
|
1254
1130
|
}
|
|
1255
1131
|
/**
|
|
1256
|
-
|
|
1257
|
-
|
|
1132
|
+
* @inheritDoc
|
|
1133
|
+
*/ destroy() {
|
|
1258
1134
|
super.destroy();
|
|
1259
1135
|
this.focusTracker.destroy();
|
|
1260
1136
|
this.keystrokes.destroy();
|
|
1261
1137
|
}
|
|
1262
1138
|
/**
|
|
1263
|
-
|
|
1264
|
-
|
|
1139
|
+
* Focuses the fist {@link #_focusables} in the actions.
|
|
1140
|
+
*/ focus() {
|
|
1265
1141
|
this._focusCycler.focusFirst();
|
|
1266
1142
|
}
|
|
1267
1143
|
/**
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
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) {
|
|
1275
1151
|
const button = new ButtonView(this.locale);
|
|
1276
1152
|
button.set({
|
|
1277
1153
|
label,
|
|
@@ -1282,10 +1158,10 @@ var unlinkIcon = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\
|
|
|
1282
1158
|
return button;
|
|
1283
1159
|
}
|
|
1284
1160
|
/**
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1161
|
+
* Creates a link href preview button.
|
|
1162
|
+
*
|
|
1163
|
+
* @returns The button view instance.
|
|
1164
|
+
*/ _createPreviewButton() {
|
|
1289
1165
|
const button = new ButtonView(this.locale);
|
|
1290
1166
|
const bind = this.bindTemplate;
|
|
1291
1167
|
const t = this.t;
|
|
@@ -1312,41 +1188,75 @@ var unlinkIcon = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\
|
|
|
1312
1188
|
button.template.eventListeners = {};
|
|
1313
1189
|
return button;
|
|
1314
1190
|
}
|
|
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
|
+
}
|
|
1315
1239
|
}
|
|
1316
1240
|
|
|
1317
1241
|
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>";
|
|
1318
1242
|
|
|
1319
1243
|
const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
1320
|
-
|
|
1321
|
-
* The link UI plugin. It introduces the `'link'` and `'unlink'` buttons and support for the <kbd>Ctrl+K</kbd> keystroke.
|
|
1322
|
-
*
|
|
1323
|
-
* It uses the
|
|
1324
|
-
* {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon plugin}.
|
|
1325
|
-
*/ class LinkUI extends Plugin {
|
|
1326
|
-
/**
|
|
1327
|
-
* The actions view displayed inside of the balloon.
|
|
1328
|
-
*/ actionsView = null;
|
|
1244
|
+
class LinkUI extends Plugin {
|
|
1329
1245
|
/**
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
/**
|
|
1333
|
-
* The contextual balloon plugin instance.
|
|
1334
|
-
*/ _balloon;
|
|
1335
|
-
/**
|
|
1336
|
-
* @inheritDoc
|
|
1337
|
-
*/ static get requires() {
|
|
1246
|
+
* @inheritDoc
|
|
1247
|
+
*/ static get requires() {
|
|
1338
1248
|
return [
|
|
1339
1249
|
ContextualBalloon
|
|
1340
1250
|
];
|
|
1341
1251
|
}
|
|
1342
1252
|
/**
|
|
1343
|
-
|
|
1344
|
-
|
|
1253
|
+
* @inheritDoc
|
|
1254
|
+
*/ static get pluginName() {
|
|
1345
1255
|
return 'LinkUI';
|
|
1346
1256
|
}
|
|
1347
1257
|
/**
|
|
1348
|
-
|
|
1349
|
-
|
|
1258
|
+
* @inheritDoc
|
|
1259
|
+
*/ init() {
|
|
1350
1260
|
const editor = this.editor;
|
|
1351
1261
|
const t = this.editor.t;
|
|
1352
1262
|
editor.editing.view.addObserver(ClickObserver);
|
|
@@ -1398,8 +1308,8 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1398
1308
|
});
|
|
1399
1309
|
}
|
|
1400
1310
|
/**
|
|
1401
|
-
|
|
1402
|
-
|
|
1311
|
+
* @inheritDoc
|
|
1312
|
+
*/ destroy() {
|
|
1403
1313
|
super.destroy();
|
|
1404
1314
|
// Destroy created UI components as they are not automatically destroyed (see ckeditor5#1341).
|
|
1405
1315
|
if (this.formView) {
|
|
@@ -1410,16 +1320,16 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1410
1320
|
}
|
|
1411
1321
|
}
|
|
1412
1322
|
/**
|
|
1413
|
-
|
|
1414
|
-
|
|
1323
|
+
* Creates views.
|
|
1324
|
+
*/ _createViews() {
|
|
1415
1325
|
this.actionsView = this._createActionsView();
|
|
1416
1326
|
this.formView = this._createFormView();
|
|
1417
1327
|
// Attach lifecycle actions to the the balloon.
|
|
1418
1328
|
this._enableUserBalloonInteractions();
|
|
1419
1329
|
}
|
|
1420
1330
|
/**
|
|
1421
|
-
|
|
1422
|
-
|
|
1331
|
+
* Creates the {@link module:link/ui/linkactionsview~LinkActionsView} instance.
|
|
1332
|
+
*/ _createActionsView() {
|
|
1423
1333
|
const editor = this.editor;
|
|
1424
1334
|
const actionsView = new LinkActionsView(editor.locale, editor.config.get('link'));
|
|
1425
1335
|
const linkCommand = editor.commands.get('link');
|
|
@@ -1449,8 +1359,8 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1449
1359
|
return actionsView;
|
|
1450
1360
|
}
|
|
1451
1361
|
/**
|
|
1452
|
-
|
|
1453
|
-
|
|
1362
|
+
* Creates the {@link module:link/ui/linkformview~LinkFormView} instance.
|
|
1363
|
+
*/ _createFormView() {
|
|
1454
1364
|
const editor = this.editor;
|
|
1455
1365
|
const linkCommand = editor.commands.get('link');
|
|
1456
1366
|
const defaultProtocol = editor.config.get('link.defaultProtocol');
|
|
@@ -1485,9 +1395,9 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1485
1395
|
return formView;
|
|
1486
1396
|
}
|
|
1487
1397
|
/**
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1398
|
+
* Creates a toolbar Link button. Clicking this button will show
|
|
1399
|
+
* a {@link #_balloon} attached to the selection.
|
|
1400
|
+
*/ _createToolbarLinkButton() {
|
|
1491
1401
|
const editor = this.editor;
|
|
1492
1402
|
const linkCommand = editor.commands.get('link');
|
|
1493
1403
|
editor.ui.componentFactory.add('link', ()=>{
|
|
@@ -1504,8 +1414,8 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1504
1414
|
});
|
|
1505
1415
|
}
|
|
1506
1416
|
/**
|
|
1507
|
-
|
|
1508
|
-
|
|
1417
|
+
* Creates a button for link command to use either in toolbar or in menu bar.
|
|
1418
|
+
*/ _createButton(ButtonClass) {
|
|
1509
1419
|
const editor = this.editor;
|
|
1510
1420
|
const locale = editor.locale;
|
|
1511
1421
|
const command = editor.commands.get('link');
|
|
@@ -1522,9 +1432,9 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1522
1432
|
return view;
|
|
1523
1433
|
}
|
|
1524
1434
|
/**
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1435
|
+
* Attaches actions that control whether the balloon panel containing the
|
|
1436
|
+
* {@link #formView} should be displayed.
|
|
1437
|
+
*/ _enableBalloonActivators() {
|
|
1528
1438
|
const editor = this.editor;
|
|
1529
1439
|
const viewDocument = editor.editing.view.document;
|
|
1530
1440
|
// Handle click on view document and show panel when selection is placed inside the link element.
|
|
@@ -1546,9 +1456,9 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1546
1456
|
});
|
|
1547
1457
|
}
|
|
1548
1458
|
/**
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1459
|
+
* Attaches actions that control whether the balloon panel containing the
|
|
1460
|
+
* {@link #formView} is visible or not.
|
|
1461
|
+
*/ _enableUserBalloonInteractions() {
|
|
1552
1462
|
// Focus the form if the balloon is visible and the Tab key has been pressed.
|
|
1553
1463
|
this.editor.keystrokes.set('Tab', (data, cancel)=>{
|
|
1554
1464
|
if (this._areActionsVisible && !this.actionsView.focusTracker.isFocused) {
|
|
@@ -1579,10 +1489,10 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1579
1489
|
});
|
|
1580
1490
|
}
|
|
1581
1491
|
/**
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1492
|
+
* Adds the {@link #actionsView} to the {@link #_balloon}.
|
|
1493
|
+
*
|
|
1494
|
+
* @internal
|
|
1495
|
+
*/ _addActionsView() {
|
|
1586
1496
|
if (!this.actionsView) {
|
|
1587
1497
|
this._createViews();
|
|
1588
1498
|
}
|
|
@@ -1595,8 +1505,8 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1595
1505
|
});
|
|
1596
1506
|
}
|
|
1597
1507
|
/**
|
|
1598
|
-
|
|
1599
|
-
|
|
1508
|
+
* Adds the {@link #formView} to the {@link #_balloon}.
|
|
1509
|
+
*/ _addFormView() {
|
|
1600
1510
|
if (!this.formView) {
|
|
1601
1511
|
this._createViews();
|
|
1602
1512
|
}
|
|
@@ -1625,12 +1535,12 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1625
1535
|
this.formView.enableCssTransitions();
|
|
1626
1536
|
}
|
|
1627
1537
|
/**
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
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() {
|
|
1634
1544
|
const linkCommand = this.editor.commands.get('link');
|
|
1635
1545
|
// Restore manual decorator states to represent the current model state. This case is important to reset the switch buttons
|
|
1636
1546
|
// when the user cancels the editing form.
|
|
@@ -1642,8 +1552,8 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1642
1552
|
}
|
|
1643
1553
|
}
|
|
1644
1554
|
/**
|
|
1645
|
-
|
|
1646
|
-
|
|
1555
|
+
* Removes the {@link #formView} from the {@link #_balloon}.
|
|
1556
|
+
*/ _removeFormView() {
|
|
1647
1557
|
if (this._isFormInPanel) {
|
|
1648
1558
|
// Blur the input element before removing it from DOM to prevent issues in some browsers.
|
|
1649
1559
|
// See https://github.com/ckeditor/ckeditor5/issues/1501.
|
|
@@ -1658,10 +1568,10 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1658
1568
|
}
|
|
1659
1569
|
}
|
|
1660
1570
|
/**
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1571
|
+
* Shows the correct UI type. It is either {@link #formView} or {@link #actionsView}.
|
|
1572
|
+
*
|
|
1573
|
+
* @internal
|
|
1574
|
+
*/ _showUI(forceVisible = false) {
|
|
1665
1575
|
if (!this.formView) {
|
|
1666
1576
|
this._createViews();
|
|
1667
1577
|
}
|
|
@@ -1692,10 +1602,10 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1692
1602
|
this._startUpdatingUI();
|
|
1693
1603
|
}
|
|
1694
1604
|
/**
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1605
|
+
* Removes the {@link #formView} from the {@link #_balloon}.
|
|
1606
|
+
*
|
|
1607
|
+
* See {@link #_addFormView}, {@link #_addActionsView}.
|
|
1608
|
+
*/ _hideUI() {
|
|
1699
1609
|
if (!this._isUIInPanel) {
|
|
1700
1610
|
return;
|
|
1701
1611
|
}
|
|
@@ -1712,11 +1622,11 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1712
1622
|
this._hideFakeVisualSelection();
|
|
1713
1623
|
}
|
|
1714
1624
|
/**
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
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() {
|
|
1720
1630
|
const editor = this.editor;
|
|
1721
1631
|
const viewDocument = editor.editing.view.document;
|
|
1722
1632
|
let prevSelectedLink = this._getSelectedLinkElement();
|
|
@@ -1752,40 +1662,40 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1752
1662
|
this.listenTo(this._balloon, 'change:visibleView', update);
|
|
1753
1663
|
}
|
|
1754
1664
|
/**
|
|
1755
|
-
|
|
1756
|
-
|
|
1665
|
+
* Returns `true` when {@link #formView} is in the {@link #_balloon}.
|
|
1666
|
+
*/ get _isFormInPanel() {
|
|
1757
1667
|
return !!this.formView && this._balloon.hasView(this.formView);
|
|
1758
1668
|
}
|
|
1759
1669
|
/**
|
|
1760
|
-
|
|
1761
|
-
|
|
1670
|
+
* Returns `true` when {@link #actionsView} is in the {@link #_balloon}.
|
|
1671
|
+
*/ get _areActionsInPanel() {
|
|
1762
1672
|
return !!this.actionsView && this._balloon.hasView(this.actionsView);
|
|
1763
1673
|
}
|
|
1764
1674
|
/**
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1675
|
+
* Returns `true` when {@link #actionsView} is in the {@link #_balloon} and it is
|
|
1676
|
+
* currently visible.
|
|
1677
|
+
*/ get _areActionsVisible() {
|
|
1768
1678
|
return !!this.actionsView && this._balloon.visibleView === this.actionsView;
|
|
1769
1679
|
}
|
|
1770
1680
|
/**
|
|
1771
|
-
|
|
1772
|
-
|
|
1681
|
+
* Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon}.
|
|
1682
|
+
*/ get _isUIInPanel() {
|
|
1773
1683
|
return this._isFormInPanel || this._areActionsInPanel;
|
|
1774
1684
|
}
|
|
1775
1685
|
/**
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1686
|
+
* Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon} and it is
|
|
1687
|
+
* currently visible.
|
|
1688
|
+
*/ get _isUIVisible() {
|
|
1779
1689
|
const visibleView = this._balloon.visibleView;
|
|
1780
1690
|
return !!this.formView && visibleView == this.formView || this._areActionsVisible;
|
|
1781
1691
|
}
|
|
1782
1692
|
/**
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
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() {
|
|
1789
1699
|
const view = this.editor.editing.view;
|
|
1790
1700
|
const model = this.editor.model;
|
|
1791
1701
|
const viewDocument = view.document;
|
|
@@ -1812,14 +1722,14 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1812
1722
|
};
|
|
1813
1723
|
}
|
|
1814
1724
|
/**
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
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() {
|
|
1823
1733
|
const view = this.editor.editing.view;
|
|
1824
1734
|
const selection = view.document.selection;
|
|
1825
1735
|
const selectedElement = selection.getSelectedElement();
|
|
@@ -1844,10 +1754,10 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1844
1754
|
}
|
|
1845
1755
|
}
|
|
1846
1756
|
/**
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
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() {
|
|
1851
1761
|
const model = this.editor.model;
|
|
1852
1762
|
model.change((writer)=>{
|
|
1853
1763
|
const range = model.document.selection.getFirstRange();
|
|
@@ -1876,8 +1786,8 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1876
1786
|
});
|
|
1877
1787
|
}
|
|
1878
1788
|
/**
|
|
1879
|
-
|
|
1880
|
-
|
|
1789
|
+
* Hides the fake visual selection created in {@link #_showFakeVisualSelection}.
|
|
1790
|
+
*/ _hideFakeVisualSelection() {
|
|
1881
1791
|
const model = this.editor.model;
|
|
1882
1792
|
if (model.markers.has(VISUAL_SELECTION_MARKER_NAME)) {
|
|
1883
1793
|
model.change((writer)=>{
|
|
@@ -1885,6 +1795,15 @@ const VISUAL_SELECTION_MARKER_NAME = 'link-ui';
|
|
|
1885
1795
|
});
|
|
1886
1796
|
}
|
|
1887
1797
|
}
|
|
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
|
+
}
|
|
1888
1807
|
}
|
|
1889
1808
|
/**
|
|
1890
1809
|
* Returns a link element if there's one among the ancestors of the provided `Position`.
|
|
@@ -1932,25 +1851,23 @@ const URL_REG_EXP = new RegExp(// Group 1: Line start or after a space.
|
|
|
1932
1851
|
'((?![-_])(?:[-_a-z0-9\\u00a1-\\uffff]{1,63}\\.))+' + // TLD identifier name.
|
|
1933
1852
|
'(?:[a-z\\u00a1-\\uffff]{2,63})' + ')' + ')$', 'i');
|
|
1934
1853
|
const URL_GROUP_IN_MATCH = 2;
|
|
1935
|
-
|
|
1936
|
-
* The autolink plugin.
|
|
1937
|
-
*/ class AutoLink extends Plugin {
|
|
1854
|
+
class AutoLink extends Plugin {
|
|
1938
1855
|
/**
|
|
1939
|
-
|
|
1940
|
-
|
|
1856
|
+
* @inheritDoc
|
|
1857
|
+
*/ static get requires() {
|
|
1941
1858
|
return [
|
|
1942
1859
|
Delete,
|
|
1943
1860
|
LinkEditing
|
|
1944
1861
|
];
|
|
1945
1862
|
}
|
|
1946
1863
|
/**
|
|
1947
|
-
|
|
1948
|
-
|
|
1864
|
+
* @inheritDoc
|
|
1865
|
+
*/ static get pluginName() {
|
|
1949
1866
|
return 'AutoLink';
|
|
1950
1867
|
}
|
|
1951
1868
|
/**
|
|
1952
|
-
|
|
1953
|
-
|
|
1869
|
+
* @inheritDoc
|
|
1870
|
+
*/ init() {
|
|
1954
1871
|
const editor = this.editor;
|
|
1955
1872
|
const selection = editor.model.document.selection;
|
|
1956
1873
|
selection.on('change:range', ()=>{
|
|
@@ -1960,17 +1877,17 @@ const URL_GROUP_IN_MATCH = 2;
|
|
|
1960
1877
|
this._enableTypingHandling();
|
|
1961
1878
|
}
|
|
1962
1879
|
/**
|
|
1963
|
-
|
|
1964
|
-
|
|
1880
|
+
* @inheritDoc
|
|
1881
|
+
*/ afterInit() {
|
|
1965
1882
|
this._enableEnterHandling();
|
|
1966
1883
|
this._enableShiftEnterHandling();
|
|
1967
1884
|
this._enablePasteLinking();
|
|
1968
1885
|
}
|
|
1969
1886
|
/**
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
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) {
|
|
1974
1891
|
if (position.textNode && position.textNode.hasAttribute('linkHref')) {
|
|
1975
1892
|
return findAttributeRange(position, 'linkHref', position.textNode.getAttribute('linkHref'), model);
|
|
1976
1893
|
} else {
|
|
@@ -1978,8 +1895,8 @@ const URL_GROUP_IN_MATCH = 2;
|
|
|
1978
1895
|
}
|
|
1979
1896
|
}
|
|
1980
1897
|
/**
|
|
1981
|
-
|
|
1982
|
-
|
|
1898
|
+
* Extends the document selection to includes all links that intersects with given `selectedRange`.
|
|
1899
|
+
*/ _selectEntireLinks(writer, selectedRange) {
|
|
1983
1900
|
const editor = this.editor;
|
|
1984
1901
|
const model = editor.model;
|
|
1985
1902
|
const selection = model.document.selection;
|
|
@@ -1995,8 +1912,8 @@ const URL_GROUP_IN_MATCH = 2;
|
|
|
1995
1912
|
}
|
|
1996
1913
|
}
|
|
1997
1914
|
/**
|
|
1998
|
-
|
|
1999
|
-
|
|
1915
|
+
* Enables autolinking on pasting a URL when some content is selected.
|
|
1916
|
+
*/ _enablePasteLinking() {
|
|
2000
1917
|
const editor = this.editor;
|
|
2001
1918
|
const model = editor.model;
|
|
2002
1919
|
const selection = model.document.selection;
|
|
@@ -2031,8 +1948,8 @@ const URL_GROUP_IN_MATCH = 2;
|
|
|
2031
1948
|
});
|
|
2032
1949
|
}
|
|
2033
1950
|
/**
|
|
2034
|
-
|
|
2035
|
-
|
|
1951
|
+
* Enables autolinking on typing.
|
|
1952
|
+
*/ _enableTypingHandling() {
|
|
2036
1953
|
const editor = this.editor;
|
|
2037
1954
|
const watcher = new TextWatcher(editor.model, (text)=>{
|
|
2038
1955
|
// 1. Detect <kbd>Space</kbd> after a text with a potential link.
|
|
@@ -2060,8 +1977,8 @@ const URL_GROUP_IN_MATCH = 2;
|
|
|
2060
1977
|
watcher.bind('isEnabled').to(this);
|
|
2061
1978
|
}
|
|
2062
1979
|
/**
|
|
2063
|
-
|
|
2064
|
-
|
|
1980
|
+
* Enables autolinking on the <kbd>Enter</kbd> key.
|
|
1981
|
+
*/ _enableEnterHandling() {
|
|
2065
1982
|
const editor = this.editor;
|
|
2066
1983
|
const model = editor.model;
|
|
2067
1984
|
const enterCommand = editor.commands.get('enter');
|
|
@@ -2078,8 +1995,8 @@ const URL_GROUP_IN_MATCH = 2;
|
|
|
2078
1995
|
});
|
|
2079
1996
|
}
|
|
2080
1997
|
/**
|
|
2081
|
-
|
|
2082
|
-
|
|
1998
|
+
* Enables autolinking on the <kbd>Shift</kbd>+<kbd>Enter</kbd> keyboard shortcut.
|
|
1999
|
+
*/ _enableShiftEnterHandling() {
|
|
2083
2000
|
const editor = this.editor;
|
|
2084
2001
|
const model = editor.model;
|
|
2085
2002
|
const shiftEnterCommand = editor.commands.get('shiftEnter');
|
|
@@ -2093,8 +2010,8 @@ const URL_GROUP_IN_MATCH = 2;
|
|
|
2093
2010
|
});
|
|
2094
2011
|
}
|
|
2095
2012
|
/**
|
|
2096
|
-
|
|
2097
|
-
|
|
2013
|
+
* Checks if the passed range contains a linkable text.
|
|
2014
|
+
*/ _checkAndApplyAutoLinkOnRange(rangeToCheck) {
|
|
2098
2015
|
const model = this.editor.model;
|
|
2099
2016
|
const { text, range } = getLastTextLine(rangeToCheck, model);
|
|
2100
2017
|
const url = getUrlAtTextEnd(text);
|
|
@@ -2104,11 +2021,11 @@ const URL_GROUP_IN_MATCH = 2;
|
|
|
2104
2021
|
}
|
|
2105
2022
|
}
|
|
2106
2023
|
/**
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
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) {
|
|
2112
2029
|
const model = this.editor.model;
|
|
2113
2030
|
const defaultProtocol = this.editor.config.get('link.defaultProtocol');
|
|
2114
2031
|
const fullUrl = addLinkProtocolIfApplicable(url, defaultProtocol);
|
|
@@ -2118,11 +2035,11 @@ const URL_GROUP_IN_MATCH = 2;
|
|
|
2118
2035
|
this._persistAutoLink(fullUrl, range);
|
|
2119
2036
|
}
|
|
2120
2037
|
/**
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
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) {
|
|
2126
2043
|
const model = this.editor.model;
|
|
2127
2044
|
const deletePlugin = this.editor.plugins.get('Delete');
|
|
2128
2045
|
// Enqueue change to make undo step.
|
|
@@ -2150,15 +2067,10 @@ function linkIsAlreadySet(range) {
|
|
|
2150
2067
|
return !!item && item.hasAttribute('linkHref');
|
|
2151
2068
|
}
|
|
2152
2069
|
|
|
2153
|
-
|
|
2154
|
-
* The link plugin.
|
|
2155
|
-
*
|
|
2156
|
-
* This is a "glue" plugin that loads the {@link module:link/linkediting~LinkEditing link editing feature}
|
|
2157
|
-
* and {@link module:link/linkui~LinkUI link UI feature}.
|
|
2158
|
-
*/ class Link extends Plugin {
|
|
2070
|
+
class Link extends Plugin {
|
|
2159
2071
|
/**
|
|
2160
|
-
|
|
2161
|
-
|
|
2072
|
+
* @inheritDoc
|
|
2073
|
+
*/ static get requires() {
|
|
2162
2074
|
return [
|
|
2163
2075
|
LinkEditing,
|
|
2164
2076
|
LinkUI,
|
|
@@ -2166,21 +2078,16 @@ function linkIsAlreadySet(range) {
|
|
|
2166
2078
|
];
|
|
2167
2079
|
}
|
|
2168
2080
|
/**
|
|
2169
|
-
|
|
2170
|
-
|
|
2081
|
+
* @inheritDoc
|
|
2082
|
+
*/ static get pluginName() {
|
|
2171
2083
|
return 'Link';
|
|
2172
2084
|
}
|
|
2173
2085
|
}
|
|
2174
2086
|
|
|
2175
|
-
|
|
2176
|
-
* The link image engine feature.
|
|
2177
|
-
*
|
|
2178
|
-
* It accepts the `linkHref="url"` attribute in the model for the {@link module:image/image~Image `<imageBlock>`} element
|
|
2179
|
-
* which allows linking images.
|
|
2180
|
-
*/ class LinkImageEditing extends Plugin {
|
|
2087
|
+
class LinkImageEditing extends Plugin {
|
|
2181
2088
|
/**
|
|
2182
|
-
|
|
2183
|
-
|
|
2089
|
+
* @inheritDoc
|
|
2090
|
+
*/ static get requires() {
|
|
2184
2091
|
return [
|
|
2185
2092
|
'ImageEditing',
|
|
2186
2093
|
'ImageUtils',
|
|
@@ -2188,13 +2095,13 @@ function linkIsAlreadySet(range) {
|
|
|
2188
2095
|
];
|
|
2189
2096
|
}
|
|
2190
2097
|
/**
|
|
2191
|
-
|
|
2192
|
-
|
|
2098
|
+
* @inheritDoc
|
|
2099
|
+
*/ static get pluginName() {
|
|
2193
2100
|
return 'LinkImageEditing';
|
|
2194
2101
|
}
|
|
2195
2102
|
/**
|
|
2196
|
-
|
|
2197
|
-
|
|
2103
|
+
* @inheritDoc
|
|
2104
|
+
*/ afterInit() {
|
|
2198
2105
|
const editor = this.editor;
|
|
2199
2106
|
const schema = editor.model.schema;
|
|
2200
2107
|
if (editor.plugins.has('ImageBlockEditing')) {
|
|
@@ -2211,9 +2118,9 @@ function linkIsAlreadySet(range) {
|
|
|
2211
2118
|
this._enableManualDecorators();
|
|
2212
2119
|
}
|
|
2213
2120
|
/**
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2121
|
+
* Processes {@link module:link/linkconfig~LinkDecoratorAutomaticDefinition automatic decorators} definitions and
|
|
2122
|
+
* attaches proper converters that will work when linking an image.`
|
|
2123
|
+
*/ _enableAutomaticDecorators() {
|
|
2217
2124
|
const editor = this.editor;
|
|
2218
2125
|
const command = editor.commands.get('link');
|
|
2219
2126
|
const automaticDecorators = command.automaticDecorators;
|
|
@@ -2222,9 +2129,9 @@ function linkIsAlreadySet(range) {
|
|
|
2222
2129
|
}
|
|
2223
2130
|
}
|
|
2224
2131
|
/**
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2132
|
+
* Processes transformed {@link module:link/utils/manualdecorator~ManualDecorator} instances and attaches proper converters
|
|
2133
|
+
* that will work when linking an image.
|
|
2134
|
+
*/ _enableManualDecorators() {
|
|
2228
2135
|
const editor = this.editor;
|
|
2229
2136
|
const command = editor.commands.get('link');
|
|
2230
2137
|
for (const decorator of command.manualDecorators){
|
|
@@ -2417,15 +2324,10 @@ function linkIsAlreadySet(range) {
|
|
|
2417
2324
|
};
|
|
2418
2325
|
}
|
|
2419
2326
|
|
|
2420
|
-
|
|
2421
|
-
* The link image UI plugin.
|
|
2422
|
-
*
|
|
2423
|
-
* This plugin provides the `'linkImage'` button that can be displayed in the {@link module:image/imagetoolbar~ImageToolbar}.
|
|
2424
|
-
* It can be used to wrap images in links.
|
|
2425
|
-
*/ class LinkImageUI extends Plugin {
|
|
2327
|
+
class LinkImageUI extends Plugin {
|
|
2426
2328
|
/**
|
|
2427
|
-
|
|
2428
|
-
|
|
2329
|
+
* @inheritDoc
|
|
2330
|
+
*/ static get requires() {
|
|
2429
2331
|
return [
|
|
2430
2332
|
LinkEditing,
|
|
2431
2333
|
LinkUI,
|
|
@@ -2433,13 +2335,13 @@ function linkIsAlreadySet(range) {
|
|
|
2433
2335
|
];
|
|
2434
2336
|
}
|
|
2435
2337
|
/**
|
|
2436
|
-
|
|
2437
|
-
|
|
2338
|
+
* @inheritDoc
|
|
2339
|
+
*/ static get pluginName() {
|
|
2438
2340
|
return 'LinkImageUI';
|
|
2439
2341
|
}
|
|
2440
2342
|
/**
|
|
2441
|
-
|
|
2442
|
-
|
|
2343
|
+
* @inheritDoc
|
|
2344
|
+
*/ init() {
|
|
2443
2345
|
const editor = this.editor;
|
|
2444
2346
|
const viewDocument = editor.editing.view.document;
|
|
2445
2347
|
this.listenTo(viewDocument, 'click', (evt, data)=>{
|
|
@@ -2456,12 +2358,12 @@ function linkIsAlreadySet(range) {
|
|
|
2456
2358
|
this._createToolbarLinkImageButton();
|
|
2457
2359
|
}
|
|
2458
2360
|
/**
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
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() {
|
|
2465
2367
|
const editor = this.editor;
|
|
2466
2368
|
const t = editor.t;
|
|
2467
2369
|
editor.ui.componentFactory.add('linkImage', (locale)=>{
|
|
@@ -2491,32 +2393,27 @@ function linkIsAlreadySet(range) {
|
|
|
2491
2393
|
});
|
|
2492
2394
|
}
|
|
2493
2395
|
/**
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2396
|
+
* Returns true if a linked image (either block or inline) is the only selected element
|
|
2397
|
+
* in the model document.
|
|
2398
|
+
*/ _isSelectedLinkedImage(selection) {
|
|
2497
2399
|
const selectedModelElement = selection.getSelectedElement();
|
|
2498
2400
|
const imageUtils = this.editor.plugins.get('ImageUtils');
|
|
2499
2401
|
return imageUtils.isImage(selectedModelElement) && selectedModelElement.hasAttribute('linkHref');
|
|
2500
2402
|
}
|
|
2501
2403
|
}
|
|
2502
2404
|
|
|
2503
|
-
|
|
2504
|
-
* The `LinkImage` plugin.
|
|
2505
|
-
*
|
|
2506
|
-
* This is a "glue" plugin that loads the {@link module:link/linkimageediting~LinkImageEditing link image editing feature}
|
|
2507
|
-
* and {@link module:link/linkimageui~LinkImageUI link image UI feature}.
|
|
2508
|
-
*/ class LinkImage extends Plugin {
|
|
2405
|
+
class LinkImage extends Plugin {
|
|
2509
2406
|
/**
|
|
2510
|
-
|
|
2511
|
-
|
|
2407
|
+
* @inheritDoc
|
|
2408
|
+
*/ static get requires() {
|
|
2512
2409
|
return [
|
|
2513
2410
|
LinkImageEditing,
|
|
2514
2411
|
LinkImageUI
|
|
2515
2412
|
];
|
|
2516
2413
|
}
|
|
2517
2414
|
/**
|
|
2518
|
-
|
|
2519
|
-
|
|
2415
|
+
* @inheritDoc
|
|
2416
|
+
*/ static get pluginName() {
|
|
2520
2417
|
return 'LinkImage';
|
|
2521
2418
|
}
|
|
2522
2419
|
}
|