{"version":3,"sources":["webpack:///./node_modules/@ckeditor/ckeditor5-link/theme/icons/unlink.svg","webpack:///./node_modules/@ckeditor/ckeditor5-link/theme/icons/link.svg","webpack:///./node_modules/@ckeditor/ckeditor5-link/src/utils/automaticdecorators.js","webpack:///./node_modules/@ckeditor/ckeditor5-link/src/utils.js","webpack:///./node_modules/@ckeditor/ckeditor5-link/src/linkcommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-link/src/unlinkcommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-link/src/utils/manualdecorator.js","webpack:///./node_modules/@ckeditor/ckeditor5-link/src/linkediting.js","webpack:///./node_modules/@ckeditor/ckeditor5-link/src/ui/linkformview.js","webpack:///./node_modules/@ckeditor/ckeditor5-link/src/ui/linkactionsview.js","webpack:///./node_modules/@ckeditor/ckeditor5-link/src/linkui.js","webpack:///./node_modules/@ckeditor/ckeditor5-link/src/autolink.js","webpack:///./node_modules/@ckeditor/ckeditor5-link/src/link.js"],"names":["module","exports","AutomaticDecorators","this","_definitions","Set","item","Array","isArray","forEach","add","dispatcher","on","evt","data","conversionApi","consumable","test","viewWriter","writer","viewSelection","document","selection","viewElement","createAttributeElement","attributes","priority","setCustomProperty","callback","attributeNewValue","is","wrap","getFirstRange","mapper","toViewRange","range","unwrap","viewFigure","toViewElement","linkInImage","from","getChildren","find","child","name","toMap","key","val","addClass","setAttribute","removeClass","removeAttribute","size","ATTRIBUTE_WHITESPACES","SAFE_URL","EMAIL_REG_EXP","PROTOCOL_REG_EXP","LINK_KEYSTROKE","isLinkElement","node","getCustomProperty","createLinkElement","href","linkElement","ensureSafeUrl","url","String","isSafeUrl","normalizedUrl","replace","match","getLocalizedDecorators","t","decorators","localizedDecoratorsLabels","decorator","label","normalizeDecorators","retArray","Object","entries","value","assign","id","upperFirst","push","isImageAllowed","element","schema","checkAttribute","isEmail","addLinkProtocolIfApplicable","link","defaultProtocol","protocol","isProtocolNeeded","LinkCommand","editor","manualDecorators","Collection","automaticDecorators","manualDecorator","_getDecoratorStateFromModel","model","doc","selectedElement","first","getSelectedBlocks","getAttribute","isEnabled","checkAttributeInSelection","manualDecoratorIds","truthyManualDecorators","falsyManualDecorators","change","isCollapsed","position","getFirstPosition","hasAttribute","linkRange","findAttributeRange","setSelection","createPositionAfter","end","nodeBefore","getAttributes","set","insertContent","createText","positionAfter","removeSelectionAttribute","ranges","getValidRanges","getRanges","allowedRanges","createRangeOn","rangesToUpdate","slice","_isRangeToUpdate","decoratorName","allowedRange","containsRange","Command","UnlinkCommand","linkCommand","commands","get","rangesToUnlink","ManualDecorator","defaultValue","mix","ObservableMixin","HIGHLIGHT_CLASS","DECORATOR_AUTOMATIC","DECORATOR_MANUAL","EXTERNAL_LINKS_REGEXP","LinkEditing","config","define","addTargetToExternalLinks","TwoStepCaretMovement","Input","Clipboard","extend","allowAttributes","conversion","for","attributeToElement","view","elementToAttribute","linkDecorators","_enableAutomaticDecorators","filter","mode","_enableManualDecorators","twoStepCaretMovementPlugin","plugins","registerAttribute","inlineHighlight","_enableInsertContentSelectionAttributesFixer","_enableClickingAfterLink","_enableTypingOverLink","_handleDeleteContentAfterLink","automaticDecoratorDefinitions","command","target","rel","length","getDispatcher","manualDecoratorDefinitions","manualDecoratorName","listenTo","anchor","nodeAfter","removeLinkAttributesFromSelection","editing","addObserver","MouseObserver","clicked","isTouching","start","selectionAttributes","deletedContent","isTyping","shouldCopyAttributes","attribute","shouldPreserveAttributes","hasBackspacePressed","domEvent","keyCode","keyCodes","backspace","linkHref","containsPosition","isEqual","enqueueChange","Plugin","firstPosition","lastPosition","getLastPosition","nodeAtFirstPosition","nodeAtLastPosition","textNode","createRange","input","isInput","batch","LinkFormView","locale","focusTracker","FocusTracker","keystrokes","KeystrokeHandler","urlInputView","_createUrlInput","saveButtonView","_createButton","icons","check","type","cancelButtonView","cancel","_manualDecoratorSwitches","_createManualDecoratorSwitches","children","_createFormChildren","_focusables","ViewCollection","_focusCycler","FocusCycler","focusables","keystrokeHandler","actions","focusPrevious","focusNext","classList","setTemplate","tag","class","tabindex","injectCssTransitionDisabler","reduce","accumulator","switchButton","isOn","submitHandler","childViews","v","focusFirst","labeledInput","LabeledFieldView","createLabeledInputText","icon","className","eventName","button","ButtonView","tooltip","extendTemplate","delegate","to","switches","createCollection","SwitchButtonView","withText","bind","toMany","decoratorValue","commandValue","undefined","additionalButtonsView","View","map","LinkActionsView","previewButtonView","_createPreviewButton","unlinkButtonView","unlinkIcon","editButtonView","pencil","bindTemplate","template","eventListeners","VISUAL_SELECTION_MARKER_NAME","LinkUI","ClickObserver","actionsView","_createActionsView","formView","_createFormView","_balloon","ContextualBalloon","_createToolbarLinkButton","_enableUserBalloonInteractions","markerToHighlight","classes","markerToElement","destroy","unlinkCommand","_addFormView","execute","_hideUI","fieldView","parsedUrl","getDecoratorSwitchesState","_closeFormView","keyEvtData","_showUI","ui","componentFactory","linkIcon","keystroke","isToggleable","viewDocument","parentLink","_getSelectedLinkElement","_areActionsVisible","isFocused","focus","_isUIVisible","clickOutsideHandler","emitter","activator","_isUIInPanel","contextElements","_areActionsInPanel","_getBalloonPositionData","_isFormInPanel","disableCssTransitions","visibleView","select","enableCssTransitions","restoreManualDecoratorStates","_removeFormView","remove","_hideFakeVisualSelection","forceVisible","_addActionsView","showStack","_showFakeVisualSelection","_startUpdatingUI","stopListening","prevSelectedLink","prevSelectionParent","getSelectionParent","update","selectedLink","selectionParent","updatePosition","getAncestors","reverse","markers","has","markerViewElements","markerNameToElements","newRange","createPositionBefore","domConverter","viewRangeToDom","targetLink","mapViewToDom","findLinkElementAncestor","getTrimmed","startLink","endLink","createRangeIn","updateMarker","isAtEnd","startPosition","getLastMatchingPosition","isContent","boundaries","addMarker","usingOperation","affectsData","removeMarker","hasView","ancestor","MIN_LINK_LENGTH_WITH_SPACE_AT_END","URL_REG_EXP","RegExp","URL_GROUP_IN_MATCH","AutoLink","parent","_enableTypingHandling","_enableEnterHandling","_enableShiftEnterHandling","watcher","TextWatcher","text","isSingleSpaceAtTheEnd","getUrlAtTextEnd","substr","linkEnd","getShiftedBy","linkStart","_applyAutoLink","enterCommand","previousSibling","rangeToCheck","_checkAndApplyAutoLinkOnRange","shiftEnterCommand","createPositionAt","getLastTextLine","isLinkAllowedOnRange","exec","createSelection","Link"],"mappings":"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","file":"js/chunk-vendors~c6b7b68c.781d0b52.js","sourcesContent":["module.exports = \"\"","module.exports = \"\"","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md.\n */\n\n/**\n * @module link/utils\n */\n\nimport { toMap } from 'ckeditor5/src/utils';\n\n/**\n * Helper class that ties together all {@link module:link/link~LinkDecoratorAutomaticDefinition} and provides\n * the {@link module:engine/conversion/downcasthelpers~DowncastHelpers#attributeToElement downcast dispatchers} for them.\n */\nexport default class AutomaticDecorators {\n\tconstructor() {\n\t\t/**\n\t\t * Stores the definition of {@link module:link/link~LinkDecoratorAutomaticDefinition automatic decorators}.\n\t\t * This data is used as a source for a downcast dispatcher to create a proper conversion to output data.\n\t\t *\n\t\t * @private\n\t\t * @type {Set}\n\t\t */\n\t\tthis._definitions = new Set();\n\t}\n\n\t/**\n\t * Gives information about the number of decorators stored in the {@link module:link/utils~AutomaticDecorators} instance.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Number}\n\t */\n\tget length() {\n\t\treturn this._definitions.size;\n\t}\n\n\t/**\n\t * Adds automatic decorator objects or an array with them to be used during downcasting.\n\t *\n\t * @param {module:link/link~LinkDecoratorAutomaticDefinition|Array.} item\n\t * A configuration object of automatic rules for decorating links. It might also be an array of such objects.\n\t */\n\tadd( item ) {\n\t\tif ( Array.isArray( item ) ) {\n\t\t\titem.forEach( item => this._definitions.add( item ) );\n\t\t} else {\n\t\t\tthis._definitions.add( item );\n\t\t}\n\t}\n\n\t/**\n\t * Provides the conversion helper used in the {@link module:engine/conversion/downcasthelpers~DowncastHelpers#add} method.\n\t *\n\t * @returns {Function} A dispatcher function used as conversion helper\n\t * in {@link module:engine/conversion/downcasthelpers~DowncastHelpers#add}.\n\t */\n\tgetDispatcher() {\n\t\treturn dispatcher => {\n\t\t\tdispatcher.on( 'attribute:linkHref', ( evt, data, conversionApi ) => {\n\t\t\t\t// There is only test as this behavior decorates links and\n\t\t\t\t// it is run before dispatcher which actually consumes this node.\n\t\t\t\t// This allows on writing own dispatcher with highest priority,\n\t\t\t\t// which blocks both native converter and this additional decoration.\n\t\t\t\tif ( !conversionApi.consumable.test( data.item, 'attribute:linkHref' ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst viewWriter = conversionApi.writer;\n\t\t\t\tconst viewSelection = viewWriter.document.selection;\n\n\t\t\t\tfor ( const item of this._definitions ) {\n\t\t\t\t\tconst viewElement = viewWriter.createAttributeElement( 'a', item.attributes, {\n\t\t\t\t\t\tpriority: 5\n\t\t\t\t\t} );\n\t\t\t\t\tviewWriter.setCustomProperty( 'link', true, viewElement );\n\t\t\t\t\tif ( item.callback( data.attributeNewValue ) ) {\n\t\t\t\t\t\tif ( data.item.is( 'selection' ) ) {\n\t\t\t\t\t\t\tviewWriter.wrap( viewSelection.getFirstRange(), viewElement );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tviewWriter.wrap( conversionApi.mapper.toViewRange( data.range ), viewElement );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tviewWriter.unwrap( conversionApi.mapper.toViewRange( data.range ), viewElement );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}, { priority: 'high' } );\n\t\t};\n\t}\n\n\t/**\n\t * Provides the conversion helper used in the {@link module:engine/conversion/downcasthelpers~DowncastHelpers#add} method\n\t * when linking images.\n\t *\n\t * @returns {Function} A dispatcher function used as conversion helper\n\t * in {@link module:engine/conversion/downcasthelpers~DowncastHelpers#add}.\n\t */\n\tgetDispatcherForLinkedImage() {\n\t\treturn dispatcher => {\n\t\t\tdispatcher.on( 'attribute:linkHref:image', ( evt, data, conversionApi ) => {\n\t\t\t\tconst viewFigure = conversionApi.mapper.toViewElement( data.item );\n\t\t\t\tconst linkInImage = Array.from( viewFigure.getChildren() ).find( child => child.name === 'a' );\n\n\t\t\t\tfor ( const item of this._definitions ) {\n\t\t\t\t\tconst attributes = toMap( item.attributes );\n\n\t\t\t\t\tif ( item.callback( data.attributeNewValue ) ) {\n\t\t\t\t\t\tfor ( const [ key, val ] of attributes ) {\n\t\t\t\t\t\t\tif ( key === 'class' ) {\n\t\t\t\t\t\t\t\tconversionApi.writer.addClass( val, linkInImage );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconversionApi.writer.setAttribute( key, val, linkInImage );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor ( const [ key, val ] of attributes ) {\n\t\t\t\t\t\t\tif ( key === 'class' ) {\n\t\t\t\t\t\t\t\tconversionApi.writer.removeClass( val, linkInImage );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconversionApi.writer.removeAttribute( key, linkInImage );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t};\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module link/utils\n */\n\nimport { upperFirst } from 'lodash-es';\n\nconst ATTRIBUTE_WHITESPACES = /[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205f\\u3000]/g; // eslint-disable-line no-control-regex\nconst SAFE_URL = /^(?:(?:https?|ftps?|mailto):|[^a-z]|[a-z+.-]+(?:[^a-z+.:-]|$))/i;\n\n// Simplified email test - should be run over previously found URL.\nconst EMAIL_REG_EXP = /^[\\S]+@((?![-_])(?:[-\\w\\u00a1-\\uffff]{0,63}[^-_]\\.))+(?:[a-z\\u00a1-\\uffff]{2,})$/i;\n\n// The regex checks for the protocol syntax ('xxxx://' or 'xxxx:')\n// or non-word characters at the beginning of the link ('/', '#' etc.).\nconst PROTOCOL_REG_EXP = /^((\\w+:(\\/{2,})?)|(\\W))/i;\n\n/**\n * A keystroke used by the {@link module:link/linkui~LinkUI link UI feature}.\n */\nexport const LINK_KEYSTROKE = 'Ctrl+K';\n\n/**\n * Returns `true` if a given view node is the link element.\n *\n * @param {module:engine/view/node~Node} node\n * @returns {Boolean}\n */\nexport function isLinkElement( node ) {\n\treturn node.is( 'attributeElement' ) && !!node.getCustomProperty( 'link' );\n}\n\n/**\n * Creates a link {@link module:engine/view/attributeelement~AttributeElement} with the provided `href` attribute.\n *\n * @param {String} href\n * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi\n * @returns {module:engine/view/attributeelement~AttributeElement}\n */\nexport function createLinkElement( href, { writer } ) {\n\t// Priority 5 - https://github.com/ckeditor/ckeditor5-link/issues/121.\n\tconst linkElement = writer.createAttributeElement( 'a', { href }, { priority: 5 } );\n\twriter.setCustomProperty( 'link', true, linkElement );\n\n\treturn linkElement;\n}\n\n/**\n * Returns a safe URL based on a given value.\n *\n * A URL is considered safe if it is safe for the user (does not contain any malicious code).\n *\n * If a URL is considered unsafe, a simple `\"#\"` is returned.\n *\n * @protected\n * @param {*} url\n * @returns {String} Safe URL.\n */\nexport function ensureSafeUrl( url ) {\n\turl = String( url );\n\n\treturn isSafeUrl( url ) ? url : '#';\n}\n\n// Checks whether the given URL is safe for the user (does not contain any malicious code).\n//\n// @param {String} url URL to check.\nfunction isSafeUrl( url ) {\n\tconst normalizedUrl = url.replace( ATTRIBUTE_WHITESPACES, '' );\n\n\treturn normalizedUrl.match( SAFE_URL );\n}\n\n/**\n * Returns the {@link module:link/link~LinkConfig#decorators `config.link.decorators`} configuration processed\n * to respect the locale of the editor, i.e. to display the {@link module:link/link~LinkDecoratorManualDefinition label}\n * in the correct language.\n *\n * **Note**: Only the few most commonly used labels are translated automatically. Other labels should be manually\n * translated in the {@link module:link/link~LinkConfig#decorators `config.link.decorators`} configuration.\n *\n * @param {module:utils/locale~Locale#t} t shorthand for {@link module:utils/locale~Locale#t Locale#t}\n * @param {Array.} The decorator reference\n * where the label values should be localized.\n * @returns {Array.}\n */\nexport function getLocalizedDecorators( t, decorators ) {\n\tconst localizedDecoratorsLabels = {\n\t\t'Open in a new tab': t( 'Open in a new tab' ),\n\t\t'Downloadable': t( 'Downloadable' )\n\t};\n\n\tdecorators.forEach( decorator => {\n\t\tif ( decorator.label && localizedDecoratorsLabels[ decorator.label ] ) {\n\t\t\tdecorator.label = localizedDecoratorsLabels[ decorator.label ];\n\t\t}\n\t\treturn decorator;\n\t} );\n\n\treturn decorators;\n}\n\n/**\n * Converts an object with defined decorators to a normalized array of decorators. The `id` key is added for each decorator and\n * is used as the attribute's name in the model.\n *\n * @param {Object.} decorators\n * @returns {Array.}\n */\nexport function normalizeDecorators( decorators ) {\n\tconst retArray = [];\n\n\tif ( decorators ) {\n\t\tfor ( const [ key, value ] of Object.entries( decorators ) ) {\n\t\t\tconst decorator = Object.assign(\n\t\t\t\t{},\n\t\t\t\tvalue,\n\t\t\t\t{ id: `link${ upperFirst( key ) }` }\n\t\t\t);\n\t\t\tretArray.push( decorator );\n\t\t}\n\t}\n\n\treturn retArray;\n}\n\n/**\n * Returns `true` if the specified `element` is an image and it can be linked (the element allows having the `linkHref` attribute).\n *\n * @params {module:engine/model/element~Element|null} element\n * @params {module:engine/model/schema~Schema} schema\n * @returns {Boolean}\n */\nexport function isImageAllowed( element, schema ) {\n\tif ( !element ) {\n\t\treturn false;\n\t}\n\n\treturn element.is( 'element', 'image' ) && schema.checkAttribute( 'image', 'linkHref' );\n}\n\n/**\n * Returns `true` if the specified `value` is an email.\n *\n * @params {String} value\n * @returns {Boolean}\n */\nexport function isEmail( value ) {\n\treturn EMAIL_REG_EXP.test( value );\n}\n\n/**\n * Adds the protocol prefix to the specified `link` when:\n *\n * * it does not contain it already, and there is a {@link module:link/link~LinkConfig#defaultProtocol `defaultProtocol` }\n * configuration value provided,\n * * or the link is an email address.\n *\n *\n * @params {String} link\n * @params {String} defaultProtocol\n * @returns {Boolean}\n */\nexport function addLinkProtocolIfApplicable( link, defaultProtocol ) {\n\tconst protocol = isEmail( link ) ? 'mailto:' : defaultProtocol;\n\tconst isProtocolNeeded = !!protocol && !PROTOCOL_REG_EXP.test( link );\n\n\treturn link && isProtocolNeeded ? protocol + link : link;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module link/linkcommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\nimport { findAttributeRange } from 'ckeditor5/src/typing';\nimport { Collection, toMap, first } from 'ckeditor5/src/utils';\n\nimport AutomaticDecorators from './utils/automaticdecorators';\nimport { isImageAllowed } from './utils';\n\n/**\n * The link command. It is used by the {@link module:link/link~Link link feature}.\n *\n * @extends module:core/command~Command\n */\nexport default class LinkCommand extends Command {\n\t/**\n\t * The value of the `'linkHref'` attribute if the start of the selection is located in a node with this attribute.\n\t *\n\t * @observable\n\t * @readonly\n\t * @member {Object|undefined} #value\n\t */\n\n\tconstructor( editor ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * A collection of {@link module:link/utils~ManualDecorator manual decorators}\n\t\t * corresponding to the {@link module:link/link~LinkConfig#decorators decorator configuration}.\n\t\t *\n\t\t * You can consider it a model with states of manual decorators added to the currently selected link.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:utils/collection~Collection}\n\t\t */\n\t\tthis.manualDecorators = new Collection();\n\n\t\t/**\n\t\t * An instance of the helper that ties together all {@link module:link/link~LinkDecoratorAutomaticDefinition}\n\t\t * that are used by the {@glink features/link link} and the {@glink features/image#linking-images linking images} features.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:link/utils~AutomaticDecorators}\n\t\t */\n\t\tthis.automaticDecorators = new AutomaticDecorators();\n\t}\n\n\t/**\n\t * Synchronizes the state of {@link #manualDecorators} with the currently present elements in the model.\n\t */\n\trestoreManualDecoratorStates() {\n\t\tfor ( const manualDecorator of this.manualDecorators ) {\n\t\t\tmanualDecorator.value = this._getDecoratorStateFromModel( manualDecorator.id );\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\n\t\tconst selectedElement = first( doc.selection.getSelectedBlocks() );\n\n\t\t// A check for the `LinkImage` plugin. If the selection contains an element, get values from the element.\n\t\t// Currently the selection reads attributes from text nodes only. See #7429 and #7465.\n\t\tif ( isImageAllowed( selectedElement, model.schema ) ) {\n\t\t\tthis.value = selectedElement.getAttribute( 'linkHref' );\n\t\t\tthis.isEnabled = model.schema.checkAttribute( selectedElement, 'linkHref' );\n\t\t} else {\n\t\t\tthis.value = doc.selection.getAttribute( 'linkHref' );\n\t\t\tthis.isEnabled = model.schema.checkAttributeInSelection( doc.selection, 'linkHref' );\n\t\t}\n\n\t\tfor ( const manualDecorator of this.manualDecorators ) {\n\t\t\tmanualDecorator.value = this._getDecoratorStateFromModel( manualDecorator.id );\n\t\t}\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * When the selection is non-collapsed, the `linkHref` attribute will be applied to nodes inside the selection, but only to\n\t * those nodes where the `linkHref` attribute is allowed (disallowed nodes will be omitted).\n\t *\n\t * When the selection is collapsed and is not inside the text with the `linkHref` attribute, a\n\t * new {@link module:engine/model/text~Text text node} with the `linkHref` attribute will be inserted in place of the caret, but\n\t * only if such element is allowed in this place. The `_data` of the inserted text will equal the `href` parameter.\n\t * The selection will be updated to wrap the just inserted text node.\n\t *\n\t * When the selection is collapsed and inside the text with the `linkHref` attribute, the attribute value will be updated.\n\t *\n\t * # Decorators and model attribute management\n\t *\n\t * There is an optional argument to this command that applies or removes model\n\t * {@glink framework/guides/architecture/editing-engine#text-attributes text attributes} brought by\n\t * {@link module:link/utils~ManualDecorator manual link decorators}.\n\t *\n\t * Text attribute names in the model correspond to the entries in the {@link module:link/link~LinkConfig#decorators configuration}.\n\t * For every decorator configured, a model text attribute exists with the \"link\" prefix. For example, a `'linkMyDecorator'` attribute\n\t * corresponds to `'myDecorator'` in the configuration.\n\t *\n\t * To learn more about link decorators, check out the {@link module:link/link~LinkConfig#decorators `config.link.decorators`}\n\t * documentation.\n\t *\n\t * Here is how to manage decorator attributes with the link command:\n\t *\n\t *\t\tconst linkCommand = editor.commands.get( 'link' );\n\t *\n\t *\t\t// Adding a new decorator attribute.\n\t *\t\tlinkCommand.execute( 'http://example.com', {\n\t *\t\t\tlinkIsExternal: true\n\t *\t\t} );\n\t *\n\t *\t\t// Removing a decorator attribute from the selection.\n\t *\t\tlinkCommand.execute( 'http://example.com', {\n\t *\t\t\tlinkIsExternal: false\n\t *\t\t} );\n\t *\n\t *\t\t// Adding multiple decorator attributes at the same time.\n\t *\t\tlinkCommand.execute( 'http://example.com', {\n\t *\t\t\tlinkIsExternal: true,\n\t *\t\t\tlinkIsDownloadable: true,\n\t *\t\t} );\n\t *\n\t *\t\t// Removing and adding decorator attributes at the same time.\n\t *\t\tlinkCommand.execute( 'http://example.com', {\n\t *\t\t\tlinkIsExternal: false,\n\t *\t\t\tlinkFoo: true,\n\t *\t\t\tlinkIsDownloadable: false,\n\t *\t\t} );\n\t *\n\t * **Note**: If the decorator attribute name is not specified, its state remains untouched.\n\t *\n\t * **Note**: {@link module:link/unlinkcommand~UnlinkCommand#execute `UnlinkCommand#execute()`} removes all\n\t * decorator attributes.\n\t *\n\t * @fires execute\n\t * @param {String} href Link destination.\n\t * @param {Object} [manualDecoratorIds={}] The information about manual decorator attributes to be applied or removed upon execution.\n\t */\n\texecute( href, manualDecoratorIds = {} ) {\n\t\tconst model = this.editor.model;\n\t\tconst selection = model.document.selection;\n\t\t// Stores information about manual decorators to turn them on/off when command is applied.\n\t\tconst truthyManualDecorators = [];\n\t\tconst falsyManualDecorators = [];\n\n\t\tfor ( const name in manualDecoratorIds ) {\n\t\t\tif ( manualDecoratorIds[ name ] ) {\n\t\t\t\ttruthyManualDecorators.push( name );\n\t\t\t} else {\n\t\t\t\tfalsyManualDecorators.push( name );\n\t\t\t}\n\t\t}\n\n\t\tmodel.change( writer => {\n\t\t\t// If selection is collapsed then update selected link or insert new one at the place of caret.\n\t\t\tif ( selection.isCollapsed ) {\n\t\t\t\tconst position = selection.getFirstPosition();\n\n\t\t\t\t// When selection is inside text with `linkHref` attribute.\n\t\t\t\tif ( selection.hasAttribute( 'linkHref' ) ) {\n\t\t\t\t\t// Then update `linkHref` value.\n\t\t\t\t\tconst linkRange = findAttributeRange( position, 'linkHref', selection.getAttribute( 'linkHref' ), model );\n\n\t\t\t\t\twriter.setAttribute( 'linkHref', href, linkRange );\n\n\t\t\t\t\ttruthyManualDecorators.forEach( item => {\n\t\t\t\t\t\twriter.setAttribute( item, true, linkRange );\n\t\t\t\t\t} );\n\n\t\t\t\t\tfalsyManualDecorators.forEach( item => {\n\t\t\t\t\t\twriter.removeAttribute( item, linkRange );\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Put the selection at the end of the updated link.\n\t\t\t\t\twriter.setSelection( writer.createPositionAfter( linkRange.end.nodeBefore ) );\n\t\t\t\t}\n\t\t\t\t// If not then insert text node with `linkHref` attribute in place of caret.\n\t\t\t\t// However, since selection is collapsed, attribute value will be used as data for text node.\n\t\t\t\t// So, if `href` is empty, do not create text node.\n\t\t\t\telse if ( href !== '' ) {\n\t\t\t\t\tconst attributes = toMap( selection.getAttributes() );\n\n\t\t\t\t\tattributes.set( 'linkHref', href );\n\n\t\t\t\t\ttruthyManualDecorators.forEach( item => {\n\t\t\t\t\t\tattributes.set( item, true );\n\t\t\t\t\t} );\n\n\t\t\t\t\tconst { end: positionAfter } = model.insertContent( writer.createText( href, attributes ), position );\n\n\t\t\t\t\t// Put the selection at the end of the inserted link.\n\t\t\t\t\t// Using end of range returned from insertContent in case nodes with the same attributes got merged.\n\t\t\t\t\twriter.setSelection( positionAfter );\n\t\t\t\t}\n\n\t\t\t\t// Remove the `linkHref` attribute and all link decorators from the selection.\n\t\t\t\t// It stops adding a new content into the link element.\n\t\t\t\t[ 'linkHref', ...truthyManualDecorators, ...falsyManualDecorators ].forEach( item => {\n\t\t\t\t\twriter.removeSelectionAttribute( item );\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\t// If selection has non-collapsed ranges, we change attribute on nodes inside those ranges\n\t\t\t\t// omitting nodes where the `linkHref` attribute is disallowed.\n\t\t\t\tconst ranges = model.schema.getValidRanges( selection.getRanges(), 'linkHref' );\n\n\t\t\t\t// But for the first, check whether the `linkHref` attribute is allowed on selected blocks (e.g. the \"image\" element).\n\t\t\t\tconst allowedRanges = [];\n\n\t\t\t\tfor ( const element of selection.getSelectedBlocks() ) {\n\t\t\t\t\tif ( model.schema.checkAttribute( element, 'linkHref' ) ) {\n\t\t\t\t\t\tallowedRanges.push( writer.createRangeOn( element ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Ranges that accept the `linkHref` attribute. Since we will iterate over `allowedRanges`, let's clone it.\n\t\t\t\tconst rangesToUpdate = allowedRanges.slice();\n\n\t\t\t\t// For all selection ranges we want to check whether given range is inside an element that accepts the `linkHref` attribute.\n\t\t\t\t// If so, we don't want to propagate applying the attribute to its children.\n\t\t\t\tfor ( const range of ranges ) {\n\t\t\t\t\tif ( this._isRangeToUpdate( range, allowedRanges ) ) {\n\t\t\t\t\t\trangesToUpdate.push( range );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( const range of rangesToUpdate ) {\n\t\t\t\t\twriter.setAttribute( 'linkHref', href, range );\n\n\t\t\t\t\ttruthyManualDecorators.forEach( item => {\n\t\t\t\t\t\twriter.setAttribute( item, true, range );\n\t\t\t\t\t} );\n\n\t\t\t\t\tfalsyManualDecorators.forEach( item => {\n\t\t\t\t\t\twriter.removeAttribute( item, range );\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Provides information whether a decorator with a given name is present in the currently processed selection.\n\t *\n\t * @private\n\t * @param {String} decoratorName The name of the manual decorator used in the model\n\t * @returns {Boolean} The information whether a given decorator is currently present in the selection.\n\t */\n\t_getDecoratorStateFromModel( decoratorName ) {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\n\t\tconst selectedElement = first( doc.selection.getSelectedBlocks() );\n\n\t\t// A check for the `LinkImage` plugin. If the selection contains an element, get values from the element.\n\t\t// Currently the selection reads attributes from text nodes only. See #7429 and #7465.\n\t\tif ( isImageAllowed( selectedElement, model.schema ) ) {\n\t\t\treturn selectedElement.getAttribute( decoratorName );\n\t\t}\n\n\t\treturn doc.selection.getAttribute( decoratorName );\n\t}\n\n\t/**\n\t * Checks whether specified `range` is inside an element that accepts the `linkHref` attribute.\n\t *\n\t * @private\n\t * @param {module:engine/view/range~Range} range A range to check.\n\t * @param {Array.} allowedRanges An array of ranges created on elements where the attribute is accepted.\n\t * @returns {Boolean}\n\t */\n\t_isRangeToUpdate( range, allowedRanges ) {\n\t\tfor ( const allowedRange of allowedRanges ) {\n\t\t\t// A range is inside an element that will have the `linkHref` attribute. Do not modify its nodes.\n\t\t\tif ( allowedRange.containsRange( range ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module link/unlinkcommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\nimport { findAttributeRange } from 'ckeditor5/src/typing';\nimport { first } from 'ckeditor5/src/utils';\n\nimport { isImageAllowed } from './utils';\n\n/**\n * The unlink command. It is used by the {@link module:link/link~Link link plugin}.\n *\n * @extends module:core/command~Command\n */\nexport default class UnlinkCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\n\t\tconst selectedElement = first( doc.selection.getSelectedBlocks() );\n\n\t\t// A check for the `LinkImage` plugin. If the selection contains an image element, get values from the element.\n\t\t// Currently the selection reads attributes from text nodes only. See #7429 and #7465.\n\t\tif ( isImageAllowed( selectedElement, model.schema ) ) {\n\t\t\tthis.isEnabled = model.schema.checkAttribute( selectedElement, 'linkHref' );\n\t\t} else {\n\t\t\tthis.isEnabled = model.schema.checkAttributeInSelection( doc.selection, 'linkHref' );\n\t\t}\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * When the selection is collapsed, it removes the `linkHref` attribute from each node with the same `linkHref` attribute value.\n\t * When the selection is non-collapsed, it removes the `linkHref` attribute from each node in selected ranges.\n\t *\n\t * # Decorators\n\t *\n\t * If {@link module:link/link~LinkConfig#decorators `config.link.decorators`} is specified,\n\t * all configured decorators are removed together with the `linkHref` attribute.\n\t *\n\t * @fires execute\n\t */\n\texecute() {\n\t\tconst editor = this.editor;\n\t\tconst model = this.editor.model;\n\t\tconst selection = model.document.selection;\n\t\tconst linkCommand = editor.commands.get( 'link' );\n\n\t\tmodel.change( writer => {\n\t\t\t// Get ranges to unlink.\n\t\t\tconst rangesToUnlink = selection.isCollapsed ?\n\t\t\t\t[ findAttributeRange(\n\t\t\t\t\tselection.getFirstPosition(),\n\t\t\t\t\t'linkHref',\n\t\t\t\t\tselection.getAttribute( 'linkHref' ),\n\t\t\t\t\tmodel\n\t\t\t\t) ] :\n\t\t\t\tmodel.schema.getValidRanges( selection.getRanges(), 'linkHref' );\n\n\t\t\t// Remove `linkHref` attribute from specified ranges.\n\t\t\tfor ( const range of rangesToUnlink ) {\n\t\t\t\twriter.removeAttribute( 'linkHref', range );\n\t\t\t\t// If there are registered custom attributes, then remove them during unlink.\n\t\t\t\tif ( linkCommand ) {\n\t\t\t\t\tfor ( const manualDecorator of linkCommand.manualDecorators ) {\n\t\t\t\t\t\twriter.removeAttribute( manualDecorator.id, range );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module link/utils\n */\n\nimport { ObservableMixin, mix } from 'ckeditor5/src/utils';\n\n/**\n * Helper class that stores manual decorators with observable {@link module:link/utils~ManualDecorator#value}\n * to support integration with the UI state. An instance of this class is a model with the state of individual manual decorators.\n * These decorators are kept as collections in {@link module:link/linkcommand~LinkCommand#manualDecorators}.\n *\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class ManualDecorator {\n\t/**\n\t * Creates a new instance of {@link module:link/utils~ManualDecorator}.\n\t *\n\t * @param {Object} config\n\t * @param {String} config.id The name of the attribute used in the model that represents a given manual decorator.\n\t * For example: `'linkIsExternal'`.\n\t * @param {String} config.label The label used in the user interface to toggle the manual decorator.\n\t * @param {Object} config.attributes A set of attributes added to output data when the decorator is active for a specific link.\n\t * Attributes should keep the format of attributes defined in {@link module:engine/view/elementdefinition~ElementDefinition}.\n\t * @param {Boolean} [config.defaultValue] Controls whether the decorator is \"on\" by default.\n\t */\n\tconstructor( { id, label, attributes, defaultValue } ) {\n\t\t/**\n\t\t * An ID of a manual decorator which is the name of the attribute in the model, for example: 'linkManualDecorator0'.\n\t\t *\n\t\t * @type {String}\n\t\t */\n\t\tthis.id = id;\n\n\t\t/**\n\t\t * The value of the current manual decorator. It reflects its state from the UI.\n\t\t *\n\t\t * @observable\n\t\t * @member {Boolean} module:link/utils~ManualDecorator#value\n\t\t */\n\t\tthis.set( 'value' );\n\n\t\t/**\n\t\t * The default value of manual decorator.\n\t\t *\n\t\t * @type {Boolean}\n\t\t */\n\t\tthis.defaultValue = defaultValue;\n\n\t\t/**\n\t\t * The label used in the user interface to toggle the manual decorator.\n\t\t *\n\t\t * @type {String}\n\t\t */\n\t\tthis.label = label;\n\n\t\t/**\n\t\t * A set of attributes added to downcasted data when the decorator is activated for a specific link.\n\t\t * Attributes should be added in a form of attributes defined in {@link module:engine/view/elementdefinition~ElementDefinition}.\n\t\t *\n\t\t * @type {Object}\n\t\t */\n\t\tthis.attributes = attributes;\n\t}\n}\n\nmix( ManualDecorator, ObservableMixin );\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module link/linkediting\n */\n\nimport { Plugin } from 'ckeditor5/src/core';\nimport { MouseObserver } from 'ckeditor5/src/engine';\nimport { Input, TwoStepCaretMovement, inlineHighlight, findAttributeRange } from 'ckeditor5/src/typing';\nimport { Clipboard } from 'ckeditor5/src/clipboard';\nimport { keyCodes } from 'ckeditor5/src/utils';\n\nimport LinkCommand from './linkcommand';\nimport UnlinkCommand from './unlinkcommand';\nimport ManualDecorator from './utils/manualdecorator';\nimport { createLinkElement, ensureSafeUrl, getLocalizedDecorators, normalizeDecorators } from './utils';\n\nimport '../theme/link.css';\n\nconst HIGHLIGHT_CLASS = 'ck-link_selected';\nconst DECORATOR_AUTOMATIC = 'automatic';\nconst DECORATOR_MANUAL = 'manual';\nconst EXTERNAL_LINKS_REGEXP = /^(https?:)?\\/\\//;\n\n/**\n * The link engine feature.\n *\n * It introduces the `linkHref=\"url\"` attribute in the model which renders to the view as a `` element\n * as well as `'link'` and `'unlink'` commands.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class LinkEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'LinkEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\t// Clipboard is required for handling cut and paste events while typing over the link.\n\t\treturn [ TwoStepCaretMovement, Input, Clipboard ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( editor ) {\n\t\tsuper( editor );\n\n\t\teditor.config.define( 'link', {\n\t\t\taddTargetToExternalLinks: false\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\t// Allow link attribute on all inline nodes.\n\t\teditor.model.schema.extend( '$text', { allowAttributes: 'linkHref' } );\n\n\t\teditor.conversion.for( 'dataDowncast' )\n\t\t\t.attributeToElement( { model: 'linkHref', view: createLinkElement } );\n\n\t\teditor.conversion.for( 'editingDowncast' )\n\t\t\t.attributeToElement( { model: 'linkHref', view: ( href, conversionApi ) => {\n\t\t\t\treturn createLinkElement( ensureSafeUrl( href ), conversionApi );\n\t\t\t} } );\n\n\t\teditor.conversion.for( 'upcast' )\n\t\t\t.elementToAttribute( {\n\t\t\t\tview: {\n\t\t\t\t\tname: 'a',\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\thref: true\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmodel: {\n\t\t\t\t\tkey: 'linkHref',\n\t\t\t\t\tvalue: viewElement => viewElement.getAttribute( 'href' )\n\t\t\t\t}\n\t\t\t} );\n\n\t\t// Create linking commands.\n\t\teditor.commands.add( 'link', new LinkCommand( editor ) );\n\t\teditor.commands.add( 'unlink', new UnlinkCommand( editor ) );\n\n\t\tconst linkDecorators = getLocalizedDecorators( editor.t, normalizeDecorators( editor.config.get( 'link.decorators' ) ) );\n\n\t\tthis._enableAutomaticDecorators( linkDecorators.filter( item => item.mode === DECORATOR_AUTOMATIC ) );\n\t\tthis._enableManualDecorators( linkDecorators.filter( item => item.mode === DECORATOR_MANUAL ) );\n\n\t\t// Enable two-step caret movement for `linkHref` attribute.\n\t\tconst twoStepCaretMovementPlugin = editor.plugins.get( TwoStepCaretMovement );\n\t\ttwoStepCaretMovementPlugin.registerAttribute( 'linkHref' );\n\n\t\t// Setup highlight over selected link.\n\t\tinlineHighlight( editor, 'linkHref', 'a', HIGHLIGHT_CLASS );\n\n\t\t// Change the attributes of the selection in certain situations after the link was inserted into the document.\n\t\tthis._enableInsertContentSelectionAttributesFixer();\n\n\t\t// Handle a click at the beginning/end of a link element.\n\t\tthis._enableClickingAfterLink();\n\n\t\t// Handle typing over the link.\n\t\tthis._enableTypingOverLink();\n\n\t\t// Handle removing the content after the link element.\n\t\tthis._handleDeleteContentAfterLink();\n\t}\n\n\t/**\n\t * Processes an array of configured {@link module:link/link~LinkDecoratorAutomaticDefinition automatic decorators}\n\t * and registers a {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher downcast dispatcher}\n\t * for each one of them. Downcast dispatchers are obtained using the\n\t * {@link module:link/utils~AutomaticDecorators#getDispatcher} method.\n\t *\n\t * **Note**: This method also activates the automatic external link decorator if enabled with\n\t * {@link module:link/link~LinkConfig#addTargetToExternalLinks `config.link.addTargetToExternalLinks`}.\n\t *\n\t * @private\n\t * @param {Array.} automaticDecoratorDefinitions\n\t */\n\t_enableAutomaticDecorators( automaticDecoratorDefinitions ) {\n\t\tconst editor = this.editor;\n\t\t// Store automatic decorators in the command instance as we do the same with manual decorators.\n\t\t// Thanks to that, `LinkImageEditing` plugin can re-use the same definitions.\n\t\tconst command = editor.commands.get( 'link' );\n\t\tconst automaticDecorators = command.automaticDecorators;\n\n\t\t// Adds a default decorator for external links.\n\t\tif ( editor.config.get( 'link.addTargetToExternalLinks' ) ) {\n\t\t\tautomaticDecorators.add( {\n\t\t\t\tid: 'linkIsExternal',\n\t\t\t\tmode: DECORATOR_AUTOMATIC,\n\t\t\t\tcallback: url => EXTERNAL_LINKS_REGEXP.test( url ),\n\t\t\t\tattributes: {\n\t\t\t\t\ttarget: '_blank',\n\t\t\t\t\trel: 'noopener noreferrer'\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tautomaticDecorators.add( automaticDecoratorDefinitions );\n\n\t\tif ( automaticDecorators.length ) {\n\t\t\teditor.conversion.for( 'downcast' ).add( automaticDecorators.getDispatcher() );\n\t\t}\n\t}\n\n\t/**\n\t * Processes an array of configured {@link module:link/link~LinkDecoratorManualDefinition manual decorators},\n\t * transforms them into {@link module:link/utils~ManualDecorator} instances and stores them in the\n\t * {@link module:link/linkcommand~LinkCommand#manualDecorators} collection (a model for manual decorators state).\n\t *\n\t * Also registers an {@link module:engine/conversion/downcasthelpers~DowncastHelpers#attributeToElement attribute-to-element}\n\t * converter for each manual decorator and extends the {@link module:engine/model/schema~Schema model's schema}\n\t * with adequate model attributes.\n\t *\n\t * @private\n\t * @param {Array.} manualDecoratorDefinitions\n\t */\n\t_enableManualDecorators( manualDecoratorDefinitions ) {\n\t\tif ( !manualDecoratorDefinitions.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst editor = this.editor;\n\t\tconst command = editor.commands.get( 'link' );\n\t\tconst manualDecorators = command.manualDecorators;\n\n\t\tmanualDecoratorDefinitions.forEach( decorator => {\n\t\t\teditor.model.schema.extend( '$text', { allowAttributes: decorator.id } );\n\n\t\t\t// Keeps reference to manual decorator to decode its name to attributes during downcast.\n\t\t\tmanualDecorators.add( new ManualDecorator( decorator ) );\n\n\t\t\teditor.conversion.for( 'downcast' ).attributeToElement( {\n\t\t\t\tmodel: decorator.id,\n\t\t\t\tview: ( manualDecoratorName, { writer } ) => {\n\t\t\t\t\tif ( manualDecoratorName ) {\n\t\t\t\t\t\tconst attributes = manualDecorators.get( decorator.id ).attributes;\n\t\t\t\t\t\tconst element = writer.createAttributeElement( 'a', attributes, { priority: 5 } );\n\t\t\t\t\t\twriter.setCustomProperty( 'link', true, element );\n\n\t\t\t\t\t\treturn element;\n\t\t\t\t\t}\n\t\t\t\t} } );\n\n\t\t\teditor.conversion.for( 'upcast' ).elementToAttribute( {\n\t\t\t\tview: {\n\t\t\t\t\tname: 'a',\n\t\t\t\t\tattributes: manualDecorators.get( decorator.id ).attributes\n\t\t\t\t},\n\t\t\t\tmodel: {\n\t\t\t\t\tkey: decorator.id\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\t}\n\n\t/**\n\t * Starts listening to {@link module:engine/model/model~Model#event:insertContent} and corrects the model\n\t * selection attributes if the selection is at the end of a link after inserting the content.\n\t *\n\t * The purpose of this action is to improve the overall UX because the user is no longer \"trapped\" by the\n\t * `linkHref` attribute of the selection and they can type a \"clean\" (`linkHref`–less) text right away.\n\t *\n\t * See https://github.com/ckeditor/ckeditor5/issues/6053.\n\t *\n\t * @private\n\t */\n\t_enableInsertContentSelectionAttributesFixer() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst selection = model.document.selection;\n\t\tconst linkCommand = editor.commands.get( 'link' );\n\n\t\tthis.listenTo( model, 'insertContent', () => {\n\t\t\tconst nodeBefore = selection.anchor.nodeBefore;\n\t\t\tconst nodeAfter = selection.anchor.nodeAfter;\n\n\t\t\t// NOTE: ↰ and ↱ represent the gravity of the selection.\n\n\t\t\t// The only truly valid case is:\n\t\t\t//\n\t\t\t//\t\t ↰\n\t\t\t//\t\t...<$text linkHref=\"foo\">INSERTED[]$text>\n\t\t\t//\n\t\t\t// If the selection is not \"trapped\" by the `linkHref` attribute after inserting, there's nothing\n\t\t\t// to fix there.\n\t\t\tif ( !selection.hasAttribute( 'linkHref' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Filter out the following case where a link with the same href (e.g. INSERTED) is inserted\n\t\t\t// in the middle of an existing link:\n\t\t\t//\n\t\t\t// Before insertion:\n\t\t\t//\t\t ↰\n\t\t\t//\t\t<$text linkHref=\"foo\">l[]ink$text>\n\t\t\t//\n\t\t\t// Expected after insertion:\n\t\t\t//\t\t ↰\n\t\t\t//\t\t<$text linkHref=\"foo\">lINSERTED[]ink$text>\n\t\t\t//\n\t\t\tif ( !nodeBefore ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Filter out the following case where the selection has the \"linkHref\" attribute because the\n\t\t\t// gravity is overridden and some text with another attribute (e.g. INSERTED) is inserted:\n\t\t\t//\n\t\t\t// Before insertion:\n\t\t\t//\n\t\t\t//\t\t ↱\n\t\t\t//\t\t<$text linkHref=\"foo\">[]link$text>\n\t\t\t//\n\t\t\t// Expected after insertion:\n\t\t\t//\n\t\t\t//\t\t ↱\n\t\t\t//\t\t<$text bold=\"true\">INSERTED$text><$text linkHref=\"foo\">[]link$text>\n\t\t\t//\n\t\t\tif ( !nodeBefore.hasAttribute( 'linkHref' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Filter out the following case where a link is a inserted in the middle (or before) another link\n\t\t\t// (different URLs, so they will not merge). In this (let's say weird) case, we can leave the selection\n\t\t\t// attributes as they are because the user will end up writing in one link or another anyway.\n\t\t\t//\n\t\t\t// Before insertion:\n\t\t\t//\n\t\t\t//\t\t ↰\n\t\t\t//\t\t<$text linkHref=\"foo\">l[]ink$text>\n\t\t\t//\n\t\t\t// Expected after insertion:\n\t\t\t//\n\t\t\t//\t\t ↰\n\t\t\t//\t\t<$text linkHref=\"foo\">l$text><$text linkHref=\"bar\">INSERTED[]$text><$text linkHref=\"foo\">ink$text>\n\t\t\t//\n\t\t\tif ( nodeAfter && nodeAfter.hasAttribute( 'linkHref' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmodel.change( writer => {\n\t\t\t\tremoveLinkAttributesFromSelection( writer, linkCommand.manualDecorators );\n\t\t\t} );\n\t\t}, { priority: 'low' } );\n\t}\n\n\t/**\n\t * Starts listening to {@link module:engine/view/document~Document#event:mousedown} and\n\t * {@link module:engine/view/document~Document#event:selectionChange} and puts the selection before/after a link node\n\t * if clicked at the beginning/ending of the link.\n\t *\n\t * The purpose of this action is to allow typing around the link node directly after a click.\n\t *\n\t * See https://github.com/ckeditor/ckeditor5/issues/1016.\n\t *\n\t * @private\n\t */\n\t_enableClickingAfterLink() {\n\t\tconst editor = this.editor;\n\t\tconst linkCommand = editor.commands.get( 'link' );\n\n\t\teditor.editing.view.addObserver( MouseObserver );\n\n\t\tlet clicked = false;\n\n\t\t// Detect the click.\n\t\tthis.listenTo( editor.editing.view.document, 'mousedown', () => {\n\t\t\tclicked = true;\n\t\t} );\n\n\t\t// When the selection has changed...\n\t\tthis.listenTo( editor.editing.view.document, 'selectionChange', () => {\n\t\t\tif ( !clicked ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// ...and it was caused by the click...\n\t\t\tclicked = false;\n\n\t\t\tconst selection = editor.model.document.selection;\n\n\t\t\t// ...and no text is selected...\n\t\t\tif ( !selection.isCollapsed ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// ...and clicked text is the link...\n\t\t\tif ( !selection.hasAttribute( 'linkHref' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst position = selection.getFirstPosition();\n\t\t\tconst linkRange = findAttributeRange( position, 'linkHref', selection.getAttribute( 'linkHref' ), editor.model );\n\n\t\t\t// ...check whether clicked start/end boundary of the link.\n\t\t\t// If so, remove the `linkHref` attribute.\n\t\t\tif ( position.isTouching( linkRange.start ) || position.isTouching( linkRange.end ) ) {\n\t\t\t\teditor.model.change( writer => {\n\t\t\t\t\tremoveLinkAttributesFromSelection( writer, linkCommand.manualDecorators );\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Starts listening to {@link module:engine/model/model~Model#deleteContent} and {@link module:engine/model/model~Model#insertContent}\n\t * and checks whether typing over the link. If so, attributes of removed text are preserved and applied to the inserted text.\n\t *\n\t * The purpose of this action is to allow modifying a text without loosing the `linkHref` attribute (and other).\n\t *\n\t * See https://github.com/ckeditor/ckeditor5/issues/4762.\n\t *\n\t * @private\n\t */\n\t_enableTypingOverLink() {\n\t\tconst editor = this.editor;\n\t\tconst view = editor.editing.view;\n\n\t\t// Selection attributes when started typing over the link.\n\t\tlet selectionAttributes;\n\n\t\t// Whether pressed `Backspace` or `Delete`. If so, attributes should not be preserved.\n\t\tlet deletedContent;\n\n\t\t// Detect pressing `Backspace` / `Delete`.\n\t\tthis.listenTo( view.document, 'delete', () => {\n\t\t\tdeletedContent = true;\n\t\t}, { priority: 'high' } );\n\n\t\t// Listening to `model#deleteContent` allows detecting whether selected content was a link.\n\t\t// If so, before removing the element, we will copy its attributes.\n\t\tthis.listenTo( editor.model, 'deleteContent', () => {\n\t\t\tconst selection = editor.model.document.selection;\n\n\t\t\t// Copy attributes only if anything is selected.\n\t\t\tif ( selection.isCollapsed ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// When the content was deleted, do not preserve attributes.\n\t\t\tif ( deletedContent ) {\n\t\t\t\tdeletedContent = false;\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Enabled only when typing.\n\t\t\tif ( !isTyping( editor ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( shouldCopyAttributes( editor.model ) ) {\n\t\t\t\tselectionAttributes = selection.getAttributes();\n\t\t\t}\n\t\t}, { priority: 'high' } );\n\n\t\t// Listening to `model#insertContent` allows detecting the content insertion.\n\t\t// We want to apply attributes that were removed while typing over the link.\n\t\tthis.listenTo( editor.model, 'insertContent', ( evt, [ element ] ) => {\n\t\t\tdeletedContent = false;\n\n\t\t\t// Enabled only when typing.\n\t\t\tif ( !isTyping( editor ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( !selectionAttributes ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\teditor.model.change( writer => {\n\t\t\t\tfor ( const [ attribute, value ] of selectionAttributes ) {\n\t\t\t\t\twriter.setAttribute( attribute, value, element );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tselectionAttributes = null;\n\t\t}, { priority: 'high' } );\n\t}\n\n\t/**\n\t * Starts listening to {@link module:engine/model/model~Model#deleteContent} and checks whether\n\t * removing a content right after the \"linkHref\" attribute.\n\t *\n\t * If so, the selection should not preserve the `linkHref` attribute. However, if\n\t * the {@link module:typing/twostepcaretmovement~TwoStepCaretMovement} plugin is active and\n\t * the selection has the \"linkHref\" attribute due to overriden gravity (at the end), the `linkHref` attribute should stay untouched.\n\t *\n\t * The purpose of this action is to allow removing the link text and keep the selection outside the link.\n\t *\n\t * See https://github.com/ckeditor/ckeditor5/issues/7521.\n\t *\n\t * @private\n\t */\n\t_handleDeleteContentAfterLink() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst selection = model.document.selection;\n\t\tconst view = editor.editing.view;\n\t\tconst linkCommand = editor.commands.get( 'link' );\n\n\t\t// A flag whether attributes `linkHref` attribute should be preserved.\n\t\tlet shouldPreserveAttributes = false;\n\n\t\t// A flag whether the `Backspace` key was pressed.\n\t\tlet hasBackspacePressed = false;\n\n\t\t// Detect pressing `Backspace`.\n\t\tthis.listenTo( view.document, 'delete', ( evt, data ) => {\n\t\t\thasBackspacePressed = data.domEvent.keyCode === keyCodes.backspace;\n\t\t}, { priority: 'high' } );\n\n\t\t// Before removing the content, check whether the selection is inside a link or at the end of link but with 2-SCM enabled.\n\t\t// If so, we want to preserve link attributes.\n\t\tthis.listenTo( model, 'deleteContent', () => {\n\t\t\t// Reset the state.\n\t\t\tshouldPreserveAttributes = false;\n\n\t\t\tconst position = selection.getFirstPosition();\n\t\t\tconst linkHref = selection.getAttribute( 'linkHref' );\n\n\t\t\tif ( !linkHref ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst linkRange = findAttributeRange( position, 'linkHref', linkHref, model );\n\n\t\t\t// Preserve `linkHref` attribute if the selection is in the middle of the link or\n\t\t\t// the selection is at the end of the link and 2-SCM is activated.\n\t\t\tshouldPreserveAttributes = linkRange.containsPosition( position ) || linkRange.end.isEqual( position );\n\t\t}, { priority: 'high' } );\n\n\t\t// After removing the content, check whether the current selection should preserve the `linkHref` attribute.\n\t\tthis.listenTo( model, 'deleteContent', () => {\n\t\t\t// If didn't press `Backspace`.\n\t\t\tif ( !hasBackspacePressed ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\thasBackspacePressed = false;\n\n\t\t\t// Disable the mechanism if inside a link (`<$text url=\"foo\">F[]oo$text>` or <$text url=\"foo\">Foo[]$text>`).\n\t\t\tif ( shouldPreserveAttributes ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Use `model.enqueueChange()` in order to execute the callback at the end of the changes process.\n\t\t\teditor.model.enqueueChange( writer => {\n\t\t\t\tremoveLinkAttributesFromSelection( writer, linkCommand.manualDecorators );\n\t\t\t} );\n\t\t}, { priority: 'low' } );\n\t}\n}\n\n// Make the selection free of link-related model attributes.\n// All link-related model attributes start with \"link\". That includes not only \"linkHref\"\n// but also all decorator attributes (they have dynamic names).\n//\n// @param {module:engine/model/writer~Writer} writer\n// @param {module:utils/collection~Collection} manualDecorators\nfunction removeLinkAttributesFromSelection( writer, manualDecorators ) {\n\twriter.removeSelectionAttribute( 'linkHref' );\n\n\tfor ( const decorator of manualDecorators ) {\n\t\twriter.removeSelectionAttribute( decorator.id );\n\t}\n}\n\n// Checks whether selection's attributes should be copied to the new inserted text.\n//\n// @param {module:engine/model/model~Model} model\n// @returns {Boolean}\nfunction shouldCopyAttributes( model ) {\n\tconst selection = model.document.selection;\n\tconst firstPosition = selection.getFirstPosition();\n\tconst lastPosition = selection.getLastPosition();\n\tconst nodeAtFirstPosition = firstPosition.nodeAfter;\n\n\t// The text link node does not exist...\n\tif ( !nodeAtFirstPosition ) {\n\t\treturn false;\n\t}\n\n\t// ...or it isn't the text node...\n\tif ( !nodeAtFirstPosition.is( '$text' ) ) {\n\t\treturn false;\n\t}\n\n\t// ...or isn't the link.\n\tif ( !nodeAtFirstPosition.hasAttribute( 'linkHref' ) ) {\n\t\treturn false;\n\t}\n\n\t// `textNode` = the position is inside the link element.\n\t// `nodeBefore` = the position is at the end of the link element.\n\tconst nodeAtLastPosition = lastPosition.textNode || lastPosition.nodeBefore;\n\n\t// If both references the same node selection contains a single text node.\n\tif ( nodeAtFirstPosition === nodeAtLastPosition ) {\n\t\treturn true;\n\t}\n\n\t// If nodes are not equal, maybe the link nodes has defined additional attributes inside.\n\t// First, we need to find the entire link range.\n\tconst linkRange = findAttributeRange( firstPosition, 'linkHref', nodeAtFirstPosition.getAttribute( 'linkHref' ), model );\n\n\t// Then we can check whether selected range is inside the found link range. If so, attributes should be preserved.\n\treturn linkRange.containsRange( model.createRange( firstPosition, lastPosition ), true );\n}\n\n// Checks whether provided changes were caused by typing.\n//\n// @params {module:core/editor/editor~Editor} editor\n// @returns {Boolean}\nfunction isTyping( editor ) {\n\tconst input = editor.plugins.get( 'Input' );\n\n\treturn input.isInput( editor.model.change( writer => writer.batch ) );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module link/ui/linkformview\n */\n\nimport {\n\tButtonView,\n\tFocusCycler,\n\tLabeledFieldView,\n\tSwitchButtonView,\n\tView,\n\tViewCollection,\n\tcreateLabeledInputText,\n\tinjectCssTransitionDisabler,\n\tsubmitHandler\n} from 'ckeditor5/src/ui';\nimport { FocusTracker, KeystrokeHandler } from 'ckeditor5/src/utils';\nimport { icons } from 'ckeditor5/src/core';\n\n// See: #8833.\n// eslint-disable-next-line ckeditor5-rules/ckeditor-imports\nimport '@ckeditor/ckeditor5-ui/theme/components/responsive-form/responsiveform.css';\nimport '../../theme/linkform.css';\n\n/**\n * The link form view controller class.\n *\n * See {@link module:link/ui/linkformview~LinkFormView}.\n *\n * @extends module:ui/view~View\n */\nexport default class LinkFormView extends View {\n\t/**\n\t * Creates an instance of the {@link module:link/ui/linkformview~LinkFormView} class.\n\t *\n\t * Also see {@link #render}.\n\t *\n\t * @param {module:utils/locale~Locale} [locale] The localization services instance.\n\t * @param {module:link/linkcommand~LinkCommand} linkCommand Reference to {@link module:link/linkcommand~LinkCommand}.\n\t * @param {String} [protocol] A value of a protocol to be displayed in the input's placeholder.\n\t */\n\tconstructor( locale, linkCommand ) {\n\t\tsuper( locale );\n\n\t\tconst t = locale.t;\n\n\t\t/**\n\t\t * Tracks information about DOM focus in the form.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/focustracker~FocusTracker}\n\t\t */\n\t\tthis.focusTracker = new FocusTracker();\n\n\t\t/**\n\t\t * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/keystrokehandler~KeystrokeHandler}\n\t\t */\n\t\tthis.keystrokes = new KeystrokeHandler();\n\n\t\t/**\n\t\t * The URL input view.\n\t\t *\n\t\t * @member {module:ui/labeledfield/labeledfieldview~LabeledFieldView}\n\t\t */\n\t\tthis.urlInputView = this._createUrlInput();\n\n\t\t/**\n\t\t * The Save button view.\n\t\t *\n\t\t * @member {module:ui/button/buttonview~ButtonView}\n\t\t */\n\t\tthis.saveButtonView = this._createButton( t( 'Save' ), icons.check, 'ck-button-save' );\n\t\tthis.saveButtonView.type = 'submit';\n\n\t\t/**\n\t\t * The Cancel button view.\n\t\t *\n\t\t * @member {module:ui/button/buttonview~ButtonView}\n\t\t */\n\t\tthis.cancelButtonView = this._createButton( t( 'Cancel' ), icons.cancel, 'ck-button-cancel', 'cancel' );\n\n\t\t/**\n\t\t * A collection of {@link module:ui/button/switchbuttonview~SwitchButtonView},\n\t\t * which corresponds to {@link module:link/linkcommand~LinkCommand#manualDecorators manual decorators}\n\t\t * configured in the editor.\n\t\t *\n\t\t * @private\n\t\t * @readonly\n\t\t * @type {module:ui/viewcollection~ViewCollection}\n\t\t */\n\t\tthis._manualDecoratorSwitches = this._createManualDecoratorSwitches( linkCommand );\n\n\t\t/**\n\t\t * A collection of child views in the form.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:ui/viewcollection~ViewCollection}\n\t\t */\n\t\tthis.children = this._createFormChildren( linkCommand.manualDecorators );\n\n\t\t/**\n\t\t * A collection of views that can be focused in the form.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n\t\tthis._focusables = new ViewCollection();\n\n\t\t/**\n\t\t * Helps cycling over {@link #_focusables} in the form.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {module:ui/focuscycler~FocusCycler}\n\t\t */\n\t\tthis._focusCycler = new FocusCycler( {\n\t\t\tfocusables: this._focusables,\n\t\t\tfocusTracker: this.focusTracker,\n\t\t\tkeystrokeHandler: this.keystrokes,\n\t\t\tactions: {\n\t\t\t\t// Navigate form fields backwards using the Shift + Tab keystroke.\n\t\t\t\tfocusPrevious: 'shift + tab',\n\n\t\t\t\t// Navigate form fields forwards using the Tab key.\n\t\t\t\tfocusNext: 'tab'\n\t\t\t}\n\t\t} );\n\n\t\tconst classList = [ 'ck', 'ck-link-form', 'ck-responsive-form' ];\n\n\t\tif ( linkCommand.manualDecorators.length ) {\n\t\t\tclassList.push( 'ck-link-form_layout-vertical', 'ck-vertical-form' );\n\t\t}\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'form',\n\n\t\t\tattributes: {\n\t\t\t\tclass: classList,\n\n\t\t\t\t// https://github.com/ckeditor/ckeditor5-link/issues/90\n\t\t\t\ttabindex: '-1'\n\t\t\t},\n\n\t\t\tchildren: this.children\n\t\t} );\n\n\t\tinjectCssTransitionDisabler( this );\n\t}\n\n\t/**\n\t * Obtains the state of the {@link module:ui/button/switchbuttonview~SwitchButtonView switch buttons} representing\n\t * {@link module:link/linkcommand~LinkCommand#manualDecorators manual link decorators}\n\t * in the {@link module:link/ui/linkformview~LinkFormView}.\n\t *\n\t * @returns {Object.} Key-value pairs, where the key is the name of the decorator and the value is\n\t * its state.\n\t */\n\tgetDecoratorSwitchesState() {\n\t\treturn Array.from( this._manualDecoratorSwitches ).reduce( ( accumulator, switchButton ) => {\n\t\t\taccumulator[ switchButton.name ] = switchButton.isOn;\n\t\t\treturn accumulator;\n\t\t}, {} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trender() {\n\t\tsuper.render();\n\n\t\tsubmitHandler( {\n\t\t\tview: this\n\t\t} );\n\n\t\tconst childViews = [\n\t\t\tthis.urlInputView,\n\t\t\t...this._manualDecoratorSwitches,\n\t\t\tthis.saveButtonView,\n\t\t\tthis.cancelButtonView\n\t\t];\n\n\t\tchildViews.forEach( v => {\n\t\t\t// Register the view as focusable.\n\t\t\tthis._focusables.add( v );\n\n\t\t\t// Register the view in the focus tracker.\n\t\t\tthis.focusTracker.add( v.element );\n\t\t} );\n\n\t\t// Start listening for the keystrokes coming from #element.\n\t\tthis.keystrokes.listenTo( this.element );\n\t}\n\n\t/**\n\t * Focuses the fist {@link #_focusables} in the form.\n\t */\n\tfocus() {\n\t\tthis._focusCycler.focusFirst();\n\t}\n\n\t/**\n\t * Creates a labeled input view.\n\t *\n\t * @private\n\t * @returns {module:ui/labeledfield/labeledfieldview~LabeledFieldView} Labeled field view instance.\n\t */\n\t_createUrlInput() {\n\t\tconst t = this.locale.t;\n\t\tconst labeledInput = new LabeledFieldView( this.locale, createLabeledInputText );\n\n\t\tlabeledInput.label = t( 'Link URL' );\n\n\t\treturn labeledInput;\n\t}\n\n\t/**\n\t * Creates a button view.\n\t *\n\t * @private\n\t * @param {String} label The button label.\n\t * @param {String} icon The button icon.\n\t * @param {String} className The additional button CSS class name.\n\t * @param {String} [eventName] An event name that the `ButtonView#execute` event will be delegated to.\n\t * @returns {module:ui/button/buttonview~ButtonView} The button view instance.\n\t */\n\t_createButton( label, icon, className, eventName ) {\n\t\tconst button = new ButtonView( this.locale );\n\n\t\tbutton.set( {\n\t\t\tlabel,\n\t\t\ticon,\n\t\t\ttooltip: true\n\t\t} );\n\n\t\tbutton.extendTemplate( {\n\t\t\tattributes: {\n\t\t\t\tclass: className\n\t\t\t}\n\t\t} );\n\n\t\tif ( eventName ) {\n\t\t\tbutton.delegate( 'execute' ).to( this, eventName );\n\t\t}\n\n\t\treturn button;\n\t}\n\n\t/**\n\t * Populates {@link module:ui/viewcollection~ViewCollection} of {@link module:ui/button/switchbuttonview~SwitchButtonView}\n\t * made based on {@link module:link/linkcommand~LinkCommand#manualDecorators}.\n\t *\n\t * @private\n\t * @param {module:link/linkcommand~LinkCommand} linkCommand A reference to the link command.\n\t * @returns {module:ui/viewcollection~ViewCollection} of switch buttons.\n\t */\n\t_createManualDecoratorSwitches( linkCommand ) {\n\t\tconst switches = this.createCollection();\n\n\t\tfor ( const manualDecorator of linkCommand.manualDecorators ) {\n\t\t\tconst switchButton = new SwitchButtonView( this.locale );\n\n\t\t\tswitchButton.set( {\n\t\t\t\tname: manualDecorator.id,\n\t\t\t\tlabel: manualDecorator.label,\n\t\t\t\twithText: true\n\t\t\t} );\n\n\t\t\tswitchButton.bind( 'isOn' ).toMany( [ manualDecorator, linkCommand ], 'value', ( decoratorValue, commandValue ) => {\n\t\t\t\treturn commandValue === undefined && decoratorValue === undefined ? manualDecorator.defaultValue : decoratorValue;\n\t\t\t} );\n\n\t\t\tswitchButton.on( 'execute', () => {\n\t\t\t\tmanualDecorator.set( 'value', !switchButton.isOn );\n\t\t\t} );\n\n\t\t\tswitches.add( switchButton );\n\t\t}\n\n\t\treturn switches;\n\t}\n\n\t/**\n\t * Populates the {@link #children} collection of the form.\n\t *\n\t * If {@link module:link/linkcommand~LinkCommand#manualDecorators manual decorators} are configured in the editor, it creates an\n\t * additional `View` wrapping all {@link #_manualDecoratorSwitches} switch buttons corresponding\n\t * to these decorators.\n\t *\n\t * @private\n\t * @param {module:utils/collection~Collection} manualDecorators A reference to\n\t * the collection of manual decorators stored in the link command.\n\t * @returns {module:ui/viewcollection~ViewCollection} The children of link form view.\n\t */\n\t_createFormChildren( manualDecorators ) {\n\t\tconst children = this.createCollection();\n\n\t\tchildren.add( this.urlInputView );\n\n\t\tif ( manualDecorators.length ) {\n\t\t\tconst additionalButtonsView = new View();\n\n\t\t\tadditionalButtonsView.setTemplate( {\n\t\t\t\ttag: 'ul',\n\t\t\t\tchildren: this._manualDecoratorSwitches.map( switchButton => ( {\n\t\t\t\t\ttag: 'li',\n\t\t\t\t\tchildren: [ switchButton ],\n\t\t\t\t\tattributes: {\n\t\t\t\t\t\tclass: [\n\t\t\t\t\t\t\t'ck',\n\t\t\t\t\t\t\t'ck-list__item'\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t} ) ),\n\t\t\t\tattributes: {\n\t\t\t\t\tclass: [\n\t\t\t\t\t\t'ck',\n\t\t\t\t\t\t'ck-reset',\n\t\t\t\t\t\t'ck-list'\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t} );\n\t\t\tchildren.add( additionalButtonsView );\n\t\t}\n\n\t\tchildren.add( this.saveButtonView );\n\t\tchildren.add( this.cancelButtonView );\n\n\t\treturn children;\n\t}\n}\n\n/**\n * Fired when the form view is submitted (when one of the children triggered the submit event),\n * for example with a click on {@link #saveButtonView}.\n *\n * @event submit\n */\n\n/**\n * Fired when the form view is canceled, for example with a click on {@link #cancelButtonView}.\n *\n * @event cancel\n */\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module link/ui/linkactionsview\n */\n\nimport { ButtonView, View, ViewCollection, FocusCycler } from 'ckeditor5/src/ui';\nimport { FocusTracker, KeystrokeHandler } from 'ckeditor5/src/utils';\nimport { icons } from 'ckeditor5/src/core';\n\nimport { ensureSafeUrl } from '../utils';\n\n// See: #8833.\n// eslint-disable-next-line ckeditor5-rules/ckeditor-imports\nimport '@ckeditor/ckeditor5-ui/theme/components/responsive-form/responsiveform.css';\nimport '../../theme/linkactions.css';\n\nimport unlinkIcon from '../../theme/icons/unlink.svg';\n\n/**\n * The link actions view class. This view displays the link preview, allows\n * unlinking or editing the link.\n *\n * @extends module:ui/view~View\n */\nexport default class LinkActionsView extends View {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\tconst t = locale.t;\n\n\t\t/**\n\t\t * Tracks information about DOM focus in the actions.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/focustracker~FocusTracker}\n\t\t */\n\t\tthis.focusTracker = new FocusTracker();\n\n\t\t/**\n\t\t * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:utils/keystrokehandler~KeystrokeHandler}\n\t\t */\n\t\tthis.keystrokes = new KeystrokeHandler();\n\n\t\t/**\n\t\t * The href preview view.\n\t\t *\n\t\t * @member {module:ui/view~View}\n\t\t */\n\t\tthis.previewButtonView = this._createPreviewButton();\n\n\t\t/**\n\t\t * The unlink button view.\n\t\t *\n\t\t * @member {module:ui/button/buttonview~ButtonView}\n\t\t */\n\t\tthis.unlinkButtonView = this._createButton( t( 'Unlink' ), unlinkIcon, 'unlink' );\n\n\t\t/**\n\t\t * The edit link button view.\n\t\t *\n\t\t * @member {module:ui/button/buttonview~ButtonView}\n\t\t */\n\t\tthis.editButtonView = this._createButton( t( 'Edit link' ), icons.pencil, 'edit' );\n\n\t\t/**\n\t\t * The value of the \"href\" attribute of the link to use in the {@link #previewButtonView}.\n\t\t *\n\t\t * @observable\n\t\t * @member {String}\n\t\t */\n\t\tthis.set( 'href' );\n\n\t\t/**\n\t\t * A collection of views that can be focused in the view.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {module:ui/viewcollection~ViewCollection}\n\t\t */\n\t\tthis._focusables = new ViewCollection();\n\n\t\t/**\n\t\t * Helps cycling over {@link #_focusables} in the view.\n\t\t *\n\t\t * @readonly\n\t\t * @protected\n\t\t * @member {module:ui/focuscycler~FocusCycler}\n\t\t */\n\t\tthis._focusCycler = new FocusCycler( {\n\t\t\tfocusables: this._focusables,\n\t\t\tfocusTracker: this.focusTracker,\n\t\t\tkeystrokeHandler: this.keystrokes,\n\t\t\tactions: {\n\t\t\t\t// Navigate fields backwards using the Shift + Tab keystroke.\n\t\t\t\tfocusPrevious: 'shift + tab',\n\n\t\t\t\t// Navigate fields forwards using the Tab key.\n\t\t\t\tfocusNext: 'tab'\n\t\t\t}\n\t\t} );\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'div',\n\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-link-actions',\n\t\t\t\t\t'ck-responsive-form'\n\t\t\t\t],\n\n\t\t\t\t// https://github.com/ckeditor/ckeditor5-link/issues/90\n\t\t\t\ttabindex: '-1'\n\t\t\t},\n\n\t\t\tchildren: [\n\t\t\t\tthis.previewButtonView,\n\t\t\t\tthis.editButtonView,\n\t\t\t\tthis.unlinkButtonView\n\t\t\t]\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trender() {\n\t\tsuper.render();\n\n\t\tconst childViews = [\n\t\t\tthis.previewButtonView,\n\t\t\tthis.editButtonView,\n\t\t\tthis.unlinkButtonView\n\t\t];\n\n\t\tchildViews.forEach( v => {\n\t\t\t// Register the view as focusable.\n\t\t\tthis._focusables.add( v );\n\n\t\t\t// Register the view in the focus tracker.\n\t\t\tthis.focusTracker.add( v.element );\n\t\t} );\n\n\t\t// Start listening for the keystrokes coming from #element.\n\t\tthis.keystrokes.listenTo( this.element );\n\t}\n\n\t/**\n\t * Focuses the fist {@link #_focusables} in the actions.\n\t */\n\tfocus() {\n\t\tthis._focusCycler.focusFirst();\n\t}\n\n\t/**\n\t * Creates a button view.\n\t *\n\t * @private\n\t * @param {String} label The button label.\n\t * @param {String} icon The button icon.\n\t * @param {String} [eventName] An event name that the `ButtonView#execute` event will be delegated to.\n\t * @returns {module:ui/button/buttonview~ButtonView} The button view instance.\n\t */\n\t_createButton( label, icon, eventName ) {\n\t\tconst button = new ButtonView( this.locale );\n\n\t\tbutton.set( {\n\t\t\tlabel,\n\t\t\ticon,\n\t\t\ttooltip: true\n\t\t} );\n\n\t\tbutton.delegate( 'execute' ).to( this, eventName );\n\n\t\treturn button;\n\t}\n\n\t/**\n\t * Creates a link href preview button.\n\t *\n\t * @private\n\t * @returns {module:ui/button/buttonview~ButtonView} The button view instance.\n\t */\n\t_createPreviewButton() {\n\t\tconst button = new ButtonView( this.locale );\n\t\tconst bind = this.bindTemplate;\n\t\tconst t = this.t;\n\n\t\tbutton.set( {\n\t\t\twithText: true,\n\t\t\ttooltip: t( 'Open link in new tab' )\n\t\t} );\n\n\t\tbutton.extendTemplate( {\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-link-actions__preview'\n\t\t\t\t],\n\t\t\t\thref: bind.to( 'href', href => href && ensureSafeUrl( href ) ),\n\t\t\t\ttarget: '_blank',\n\t\t\t\trel: 'noopener noreferrer'\n\t\t\t}\n\t\t} );\n\n\t\tbutton.bind( 'label' ).to( this, 'href', href => {\n\t\t\treturn href || t( 'This link has no URL' );\n\t\t} );\n\n\t\tbutton.bind( 'isEnabled' ).to( this, 'href', href => !!href );\n\n\t\tbutton.template.tag = 'a';\n\t\tbutton.template.eventListeners = {};\n\n\t\treturn button;\n\t}\n}\n\n/**\n * Fired when the {@link #editButtonView} is clicked.\n *\n * @event edit\n */\n\n/**\n * Fired when the {@link #unlinkButtonView} is clicked.\n *\n * @event unlink\n */\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module link/linkui\n */\n\nimport { Plugin } from 'ckeditor5/src/core';\nimport { ClickObserver } from 'ckeditor5/src/engine';\nimport { ButtonView, ContextualBalloon, clickOutsideHandler } from 'ckeditor5/src/ui';\n\nimport LinkFormView from './ui/linkformview';\nimport LinkActionsView from './ui/linkactionsview';\nimport { addLinkProtocolIfApplicable, isLinkElement, LINK_KEYSTROKE } from './utils';\n\nimport linkIcon from '../theme/icons/link.svg';\n\nconst VISUAL_SELECTION_MARKER_NAME = 'link-ui';\n\n/**\n * The link UI plugin. It introduces the `'link'` and `'unlink'` buttons and support for the Ctrl+K keystroke.\n *\n * It uses the\n * {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon plugin}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class LinkUI extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ ContextualBalloon ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'LinkUI';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\teditor.editing.view.addObserver( ClickObserver );\n\n\t\t/**\n\t\t * The actions view displayed inside of the balloon.\n\t\t *\n\t\t * @member {module:link/ui/linkactionsview~LinkActionsView}\n\t\t */\n\t\tthis.actionsView = this._createActionsView();\n\n\t\t/**\n\t\t * The form view displayed inside the balloon.\n\t\t *\n\t\t * @member {module:link/ui/linkformview~LinkFormView}\n\t\t */\n\t\tthis.formView = this._createFormView();\n\n\t\t/**\n\t\t * The contextual balloon plugin instance.\n\t\t *\n\t\t * @private\n\t\t * @member {module:ui/panel/balloon/contextualballoon~ContextualBalloon}\n\t\t */\n\t\tthis._balloon = editor.plugins.get( ContextualBalloon );\n\n\t\t// Create toolbar buttons.\n\t\tthis._createToolbarLinkButton();\n\n\t\t// Attach lifecycle actions to the the balloon.\n\t\tthis._enableUserBalloonInteractions();\n\n\t\t// Renders a fake visual selection marker on an expanded selection.\n\t\teditor.conversion.for( 'editingDowncast' ).markerToHighlight( {\n\t\t\tmodel: VISUAL_SELECTION_MARKER_NAME,\n\t\t\tview: {\n\t\t\t\tclasses: [ 'ck-fake-link-selection' ]\n\t\t\t}\n\t\t} );\n\n\t\t// Renders a fake visual selection marker on a collapsed selection.\n\t\teditor.conversion.for( 'editingDowncast' ).markerToElement( {\n\t\t\tmodel: VISUAL_SELECTION_MARKER_NAME,\n\t\t\tview: {\n\t\t\t\tname: 'span',\n\t\t\t\tclasses: [ 'ck-fake-link-selection', 'ck-fake-link-selection_collapsed' ]\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tsuper.destroy();\n\n\t\t// Destroy created UI components as they are not automatically destroyed (see ckeditor5#1341).\n\t\tthis.formView.destroy();\n\t}\n\n\t/**\n\t * Creates the {@link module:link/ui/linkactionsview~LinkActionsView} instance.\n\t *\n\t * @private\n\t * @returns {module:link/ui/linkactionsview~LinkActionsView} The link actions view instance.\n\t */\n\t_createActionsView() {\n\t\tconst editor = this.editor;\n\t\tconst actionsView = new LinkActionsView( editor.locale );\n\t\tconst linkCommand = editor.commands.get( 'link' );\n\t\tconst unlinkCommand = editor.commands.get( 'unlink' );\n\n\t\tactionsView.bind( 'href' ).to( linkCommand, 'value' );\n\t\tactionsView.editButtonView.bind( 'isEnabled' ).to( linkCommand );\n\t\tactionsView.unlinkButtonView.bind( 'isEnabled' ).to( unlinkCommand );\n\n\t\t// Execute unlink command after clicking on the \"Edit\" button.\n\t\tthis.listenTo( actionsView, 'edit', () => {\n\t\t\tthis._addFormView();\n\t\t} );\n\n\t\t// Execute unlink command after clicking on the \"Unlink\" button.\n\t\tthis.listenTo( actionsView, 'unlink', () => {\n\t\t\teditor.execute( 'unlink' );\n\t\t\tthis._hideUI();\n\t\t} );\n\n\t\t// Close the panel on esc key press when the **actions have focus**.\n\t\tactionsView.keystrokes.set( 'Esc', ( data, cancel ) => {\n\t\t\tthis._hideUI();\n\t\t\tcancel();\n\t\t} );\n\n\t\t// Open the form view on Ctrl+K when the **actions have focus**..\n\t\tactionsView.keystrokes.set( LINK_KEYSTROKE, ( data, cancel ) => {\n\t\t\tthis._addFormView();\n\t\t\tcancel();\n\t\t} );\n\n\t\treturn actionsView;\n\t}\n\n\t/**\n\t * Creates the {@link module:link/ui/linkformview~LinkFormView} instance.\n\t *\n\t * @private\n\t * @returns {module:link/ui/linkformview~LinkFormView} The link form view instance.\n\t */\n\t_createFormView() {\n\t\tconst editor = this.editor;\n\t\tconst linkCommand = editor.commands.get( 'link' );\n\t\tconst defaultProtocol = editor.config.get( 'link.defaultProtocol' );\n\n\t\tconst formView = new LinkFormView( editor.locale, linkCommand );\n\n\t\tformView.urlInputView.fieldView.bind( 'value' ).to( linkCommand, 'value' );\n\n\t\t// Form elements should be read-only when corresponding commands are disabled.\n\t\tformView.urlInputView.bind( 'isReadOnly' ).to( linkCommand, 'isEnabled', value => !value );\n\t\tformView.saveButtonView.bind( 'isEnabled' ).to( linkCommand );\n\n\t\t// Execute link command after clicking the \"Save\" button.\n\t\tthis.listenTo( formView, 'submit', () => {\n\t\t\tconst { value } = formView.urlInputView.fieldView.element;\n\t\t\tconst parsedUrl = addLinkProtocolIfApplicable( value, defaultProtocol );\n\t\t\teditor.execute( 'link', parsedUrl, formView.getDecoratorSwitchesState() );\n\t\t\tthis._closeFormView();\n\t\t} );\n\n\t\t// Hide the panel after clicking the \"Cancel\" button.\n\t\tthis.listenTo( formView, 'cancel', () => {\n\t\t\tthis._closeFormView();\n\t\t} );\n\n\t\t// Close the panel on esc key press when the **form has focus**.\n\t\tformView.keystrokes.set( 'Esc', ( data, cancel ) => {\n\t\t\tthis._closeFormView();\n\t\t\tcancel();\n\t\t} );\n\n\t\treturn formView;\n\t}\n\n\t/**\n\t * Creates a toolbar Link button. Clicking this button will show\n\t * a {@link #_balloon} attached to the selection.\n\t *\n\t * @private\n\t */\n\t_createToolbarLinkButton() {\n\t\tconst editor = this.editor;\n\t\tconst linkCommand = editor.commands.get( 'link' );\n\t\tconst t = editor.t;\n\n\t\t// Handle the `Ctrl+K` keystroke and show the panel.\n\t\teditor.keystrokes.set( LINK_KEYSTROKE, ( keyEvtData, cancel ) => {\n\t\t\t// Prevent focusing the search bar in FF, Chrome and Edge. See https://github.com/ckeditor/ckeditor5/issues/4811.\n\t\t\tcancel();\n\n\t\t\tif ( linkCommand.isEnabled ) {\n\t\t\t\tthis._showUI( true );\n\t\t\t}\n\t\t} );\n\n\t\teditor.ui.componentFactory.add( 'link', locale => {\n\t\t\tconst button = new ButtonView( locale );\n\n\t\t\tbutton.isEnabled = true;\n\t\t\tbutton.label = t( 'Link' );\n\t\t\tbutton.icon = linkIcon;\n\t\t\tbutton.keystroke = LINK_KEYSTROKE;\n\t\t\tbutton.tooltip = true;\n\t\t\tbutton.isToggleable = true;\n\n\t\t\t// Bind button to the command.\n\t\t\tbutton.bind( 'isEnabled' ).to( linkCommand, 'isEnabled' );\n\t\t\tbutton.bind( 'isOn' ).to( linkCommand, 'value', value => !!value );\n\n\t\t\t// Show the panel on button click.\n\t\t\tthis.listenTo( button, 'execute', () => this._showUI( true ) );\n\n\t\t\treturn button;\n\t\t} );\n\t}\n\n\t/**\n\t * Attaches actions that control whether the balloon panel containing the\n\t * {@link #formView} is visible or not.\n\t *\n\t * @private\n\t */\n\t_enableUserBalloonInteractions() {\n\t\tconst viewDocument = this.editor.editing.view.document;\n\n\t\t// Handle click on view document and show panel when selection is placed inside the link element.\n\t\t// Keep panel open until selection will be inside the same link element.\n\t\tthis.listenTo( viewDocument, 'click', () => {\n\t\t\tconst parentLink = this._getSelectedLinkElement();\n\n\t\t\tif ( parentLink ) {\n\t\t\t\t// Then show panel but keep focus inside editor editable.\n\t\t\t\tthis._showUI();\n\t\t\t}\n\t\t} );\n\n\t\t// Focus the form if the balloon is visible and the Tab key has been pressed.\n\t\tthis.editor.keystrokes.set( 'Tab', ( data, cancel ) => {\n\t\t\tif ( this._areActionsVisible && !this.actionsView.focusTracker.isFocused ) {\n\t\t\t\tthis.actionsView.focus();\n\t\t\t\tcancel();\n\t\t\t}\n\t\t}, {\n\t\t\t// Use the high priority because the link UI navigation is more important\n\t\t\t// than other feature's actions, e.g. list indentation.\n\t\t\t// https://github.com/ckeditor/ckeditor5-link/issues/146\n\t\t\tpriority: 'high'\n\t\t} );\n\n\t\t// Close the panel on the Esc key press when the editable has focus and the balloon is visible.\n\t\tthis.editor.keystrokes.set( 'Esc', ( data, cancel ) => {\n\t\t\tif ( this._isUIVisible ) {\n\t\t\t\tthis._hideUI();\n\t\t\t\tcancel();\n\t\t\t}\n\t\t} );\n\n\t\t// Close on click outside of balloon panel element.\n\t\tclickOutsideHandler( {\n\t\t\temitter: this.formView,\n\t\t\tactivator: () => this._isUIInPanel,\n\t\t\tcontextElements: [ this._balloon.view.element ],\n\t\t\tcallback: () => this._hideUI()\n\t\t} );\n\t}\n\n\t/**\n\t * Adds the {@link #actionsView} to the {@link #_balloon}.\n\t *\n\t * @protected\n\t */\n\t_addActionsView() {\n\t\tif ( this._areActionsInPanel ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._balloon.add( {\n\t\t\tview: this.actionsView,\n\t\t\tposition: this._getBalloonPositionData()\n\t\t} );\n\t}\n\n\t/**\n\t * Adds the {@link #formView} to the {@link #_balloon}.\n\t *\n\t * @protected\n\t */\n\t_addFormView() {\n\t\tif ( this._isFormInPanel ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst editor = this.editor;\n\t\tconst linkCommand = editor.commands.get( 'link' );\n\n\t\tthis.formView.disableCssTransitions();\n\n\t\tthis._balloon.add( {\n\t\t\tview: this.formView,\n\t\t\tposition: this._getBalloonPositionData()\n\t\t} );\n\n\t\t// Select input when form view is currently visible.\n\t\tif ( this._balloon.visibleView === this.formView ) {\n\t\t\tthis.formView.urlInputView.fieldView.select();\n\t\t}\n\n\t\tthis.formView.enableCssTransitions();\n\n\t\t// Make sure that each time the panel shows up, the URL field remains in sync with the value of\n\t\t// the command. If the user typed in the input, then canceled the balloon (`urlInputView.fieldView#value` stays\n\t\t// unaltered) and re-opened it without changing the value of the link command (e.g. because they\n\t\t// clicked the same link), they would see the old value instead of the actual value of the command.\n\t\t// https://github.com/ckeditor/ckeditor5-link/issues/78\n\t\t// https://github.com/ckeditor/ckeditor5-link/issues/123\n\t\tthis.formView.urlInputView.fieldView.element.value = linkCommand.value || '';\n\t}\n\n\t/**\n\t * Closes the form view. Decides whether the balloon should be hidden completely or if the action view should be shown. This is\n\t * decided upon the link command value (which has a value if the document selection is in the link).\n\t *\n\t * Additionally, if any {@link module:link/link~LinkConfig#decorators} are defined in the editor configuration, the state of\n\t * switch buttons responsible for manual decorator handling is restored.\n\t *\n\t * @private\n\t */\n\t_closeFormView() {\n\t\tconst linkCommand = this.editor.commands.get( 'link' );\n\n\t\t// Restore manual decorator states to represent the current model state. This case is important to reset the switch buttons\n\t\t// when the user cancels the editing form.\n\t\tlinkCommand.restoreManualDecoratorStates();\n\n\t\tif ( linkCommand.value !== undefined ) {\n\t\t\tthis._removeFormView();\n\t\t} else {\n\t\t\tthis._hideUI();\n\t\t}\n\t}\n\n\t/**\n\t * Removes the {@link #formView} from the {@link #_balloon}.\n\t *\n\t * @protected\n\t */\n\t_removeFormView() {\n\t\tif ( this._isFormInPanel ) {\n\t\t\t// Blur the input element before removing it from DOM to prevent issues in some browsers.\n\t\t\t// See https://github.com/ckeditor/ckeditor5/issues/1501.\n\t\t\tthis.formView.saveButtonView.focus();\n\n\t\t\tthis._balloon.remove( this.formView );\n\n\t\t\t// Because the form has an input which has focus, the focus must be brought back\n\t\t\t// to the editor. Otherwise, it would be lost.\n\t\t\tthis.editor.editing.view.focus();\n\n\t\t\tthis._hideFakeVisualSelection();\n\t\t}\n\t}\n\n\t/**\n\t * Shows the correct UI type. It is either {@link #formView} or {@link #actionsView}.\n\t *\n\t * @param {Boolean} forceVisible\n\t * @private\n\t */\n\t_showUI( forceVisible = false ) {\n\t\t// When there's no link under the selection, go straight to the editing UI.\n\t\tif ( !this._getSelectedLinkElement() ) {\n\t\t\t// Show visual selection on a text without a link when the contextual balloon is displayed.\n\t\t\t// See https://github.com/ckeditor/ckeditor5/issues/4721.\n\t\t\tthis._showFakeVisualSelection();\n\n\t\t\tthis._addActionsView();\n\n\t\t\t// Be sure panel with link is visible.\n\t\t\tif ( forceVisible ) {\n\t\t\t\tthis._balloon.showStack( 'main' );\n\t\t\t}\n\n\t\t\tthis._addFormView();\n\t\t}\n\t\t// If there's a link under the selection...\n\t\telse {\n\t\t\t// Go to the editing UI if actions are already visible.\n\t\t\tif ( this._areActionsVisible ) {\n\t\t\t\tthis._addFormView();\n\t\t\t}\n\t\t\t// Otherwise display just the actions UI.\n\t\t\telse {\n\t\t\t\tthis._addActionsView();\n\t\t\t}\n\n\t\t\t// Be sure panel with link is visible.\n\t\t\tif ( forceVisible ) {\n\t\t\t\tthis._balloon.showStack( 'main' );\n\t\t\t}\n\t\t}\n\n\t\t// Begin responding to ui#update once the UI is added.\n\t\tthis._startUpdatingUI();\n\t}\n\n\t/**\n\t * Removes the {@link #formView} from the {@link #_balloon}.\n\t *\n\t * See {@link #_addFormView}, {@link #_addActionsView}.\n\t *\n\t * @protected\n\t */\n\t_hideUI() {\n\t\tif ( !this._isUIInPanel ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst editor = this.editor;\n\n\t\tthis.stopListening( editor.ui, 'update' );\n\t\tthis.stopListening( this._balloon, 'change:visibleView' );\n\n\t\t// Make sure the focus always gets back to the editable _before_ removing the focused form view.\n\t\t// Doing otherwise causes issues in some browsers. See https://github.com/ckeditor/ckeditor5-link/issues/193.\n\t\teditor.editing.view.focus();\n\n\t\t// Remove form first because it's on top of the stack.\n\t\tthis._removeFormView();\n\n\t\t// Then remove the actions view because it's beneath the form.\n\t\tthis._balloon.remove( this.actionsView );\n\n\t\tthis._hideFakeVisualSelection();\n\t}\n\n\t/**\n\t * Makes the UI react to the {@link module:core/editor/editorui~EditorUI#event:update} event to\n\t * reposition itself when the editor UI should be refreshed.\n\t *\n\t * See: {@link #_hideUI} to learn when the UI stops reacting to the `update` event.\n\t *\n\t * @protected\n\t */\n\t_startUpdatingUI() {\n\t\tconst editor = this.editor;\n\t\tconst viewDocument = editor.editing.view.document;\n\n\t\tlet prevSelectedLink = this._getSelectedLinkElement();\n\t\tlet prevSelectionParent = getSelectionParent();\n\n\t\tconst update = () => {\n\t\t\tconst selectedLink = this._getSelectedLinkElement();\n\t\t\tconst selectionParent = getSelectionParent();\n\n\t\t\t// Hide the panel if:\n\t\t\t//\n\t\t\t// * the selection went out of the EXISTING link element. E.g. user moved the caret out\n\t\t\t// of the link,\n\t\t\t// * the selection went to a different parent when creating a NEW link. E.g. someone\n\t\t\t// else modified the document.\n\t\t\t// * the selection has expanded (e.g. displaying link actions then pressing SHIFT+Right arrow).\n\t\t\t//\n\t\t\t// Note: #_getSelectedLinkElement will return a link for a non-collapsed selection only\n\t\t\t// when fully selected.\n\t\t\tif ( ( prevSelectedLink && !selectedLink ) ||\n\t\t\t\t( !prevSelectedLink && selectionParent !== prevSelectionParent ) ) {\n\t\t\t\tthis._hideUI();\n\t\t\t}\n\t\t\t// Update the position of the panel when:\n\t\t\t// * link panel is in the visible stack\n\t\t\t// * the selection remains in the original link element,\n\t\t\t// * there was no link element in the first place, i.e. creating a new link\n\t\t\telse if ( this._isUIVisible ) {\n\t\t\t\t// If still in a link element, simply update the position of the balloon.\n\t\t\t\t// If there was no link (e.g. inserting one), the balloon must be moved\n\t\t\t\t// to the new position in the editing view (a new native DOM range).\n\t\t\t\tthis._balloon.updatePosition( this._getBalloonPositionData() );\n\t\t\t}\n\n\t\t\tprevSelectedLink = selectedLink;\n\t\t\tprevSelectionParent = selectionParent;\n\t\t};\n\n\t\tfunction getSelectionParent() {\n\t\t\treturn viewDocument.selection.focus.getAncestors()\n\t\t\t\t.reverse()\n\t\t\t\t.find( node => node.is( 'element' ) );\n\t\t}\n\n\t\tthis.listenTo( editor.ui, 'update', update );\n\t\tthis.listenTo( this._balloon, 'change:visibleView', update );\n\t}\n\n\t/**\n\t * Returns `true` when {@link #formView} is in the {@link #_balloon}.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n\tget _isFormInPanel() {\n\t\treturn this._balloon.hasView( this.formView );\n\t}\n\n\t/**\n\t * Returns `true` when {@link #actionsView} is in the {@link #_balloon}.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n\tget _areActionsInPanel() {\n\t\treturn this._balloon.hasView( this.actionsView );\n\t}\n\n\t/**\n\t * Returns `true` when {@link #actionsView} is in the {@link #_balloon} and it is\n\t * currently visible.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n\tget _areActionsVisible() {\n\t\treturn this._balloon.visibleView === this.actionsView;\n\t}\n\n\t/**\n\t * Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon}.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n\tget _isUIInPanel() {\n\t\treturn this._isFormInPanel || this._areActionsInPanel;\n\t}\n\n\t/**\n\t * Returns `true` when {@link #actionsView} or {@link #formView} is in the {@link #_balloon} and it is\n\t * currently visible.\n\t *\n\t * @readonly\n\t * @protected\n\t * @type {Boolean}\n\t */\n\tget _isUIVisible() {\n\t\tconst visibleView = this._balloon.visibleView;\n\n\t\treturn visibleView == this.formView || this._areActionsVisible;\n\t}\n\n\t/**\n\t * Returns positioning options for the {@link #_balloon}. They control the way the balloon is attached\n\t * to the target element or selection.\n\t *\n\t * If the selection is collapsed and inside a link element, the panel will be attached to the\n\t * entire link element. Otherwise, it will be attached to the selection.\n\t *\n\t * @private\n\t * @returns {module:utils/dom/position~Options}\n\t */\n\t_getBalloonPositionData() {\n\t\tconst view = this.editor.editing.view;\n\t\tconst model = this.editor.model;\n\t\tconst viewDocument = view.document;\n\t\tlet target = null;\n\n\t\tif ( model.markers.has( VISUAL_SELECTION_MARKER_NAME ) ) {\n\t\t\t// There are cases when we highlight selection using a marker (#7705, #4721).\n\t\t\tconst markerViewElements = Array.from( this.editor.editing.mapper.markerNameToElements( VISUAL_SELECTION_MARKER_NAME ) );\n\t\t\tconst newRange = view.createRange(\n\t\t\t\tview.createPositionBefore( markerViewElements[ 0 ] ),\n\t\t\t\tview.createPositionAfter( markerViewElements[ markerViewElements.length - 1 ] )\n\t\t\t);\n\n\t\t\ttarget = view.domConverter.viewRangeToDom( newRange );\n\t\t} else {\n\t\t\tconst targetLink = this._getSelectedLinkElement();\n\t\t\tconst range = viewDocument.selection.getFirstRange();\n\n\t\t\ttarget = targetLink ?\n\t\t\t\t// When selection is inside link element, then attach panel to this element.\n\t\t\t\tview.domConverter.mapViewToDom( targetLink ) :\n\t\t\t\t// Otherwise attach panel to the selection.\n\t\t\t\tview.domConverter.viewRangeToDom( range );\n\t\t}\n\n\t\treturn { target };\n\t}\n\n\t/**\n\t * Returns the link {@link module:engine/view/attributeelement~AttributeElement} under\n\t * the {@link module:engine/view/document~Document editing view's} selection or `null`\n\t * if there is none.\n\t *\n\t * **Note**: For a non–collapsed selection, the link element is only returned when **fully**\n\t * selected and the **only** element within the selection boundaries.\n\t *\n\t * @private\n\t * @returns {module:engine/view/attributeelement~AttributeElement|null}\n\t */\n\t_getSelectedLinkElement() {\n\t\tconst view = this.editor.editing.view;\n\t\tconst selection = view.document.selection;\n\n\t\tif ( selection.isCollapsed ) {\n\t\t\treturn findLinkElementAncestor( selection.getFirstPosition() );\n\t\t} else {\n\t\t\t// The range for fully selected link is usually anchored in adjacent text nodes.\n\t\t\t// Trim it to get closer to the actual link element.\n\t\t\tconst range = selection.getFirstRange().getTrimmed();\n\t\t\tconst startLink = findLinkElementAncestor( range.start );\n\t\t\tconst endLink = findLinkElementAncestor( range.end );\n\n\t\t\tif ( !startLink || startLink != endLink ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Check if the link element is fully selected.\n\t\t\tif ( view.createRangeIn( startLink ).getTrimmed().isEqual( range ) ) {\n\t\t\t\treturn startLink;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Displays a fake visual selection when the contextual balloon is displayed.\n\t *\n\t * This adds a 'link-ui' marker into the document that is rendered as a highlight on selected text fragment.\n\t *\n\t * @private\n\t */\n\t_showFakeVisualSelection() {\n\t\tconst model = this.editor.model;\n\n\t\tmodel.change( writer => {\n\t\t\tconst range = model.document.selection.getFirstRange();\n\n\t\t\tif ( model.markers.has( VISUAL_SELECTION_MARKER_NAME ) ) {\n\t\t\t\twriter.updateMarker( VISUAL_SELECTION_MARKER_NAME, { range } );\n\t\t\t} else {\n\t\t\t\tif ( range.start.isAtEnd ) {\n\t\t\t\t\tconst startPosition = range.start.getLastMatchingPosition(\n\t\t\t\t\t\t( { item } ) => !model.schema.isContent( item ),\n\t\t\t\t\t\t{ boundaries: range }\n\t\t\t\t\t);\n\n\t\t\t\t\twriter.addMarker( VISUAL_SELECTION_MARKER_NAME, {\n\t\t\t\t\t\tusingOperation: false,\n\t\t\t\t\t\taffectsData: false,\n\t\t\t\t\t\trange: writer.createRange( startPosition, range.end )\n\t\t\t\t\t} );\n\t\t\t\t} else {\n\t\t\t\t\twriter.addMarker( VISUAL_SELECTION_MARKER_NAME, {\n\t\t\t\t\t\tusingOperation: false,\n\t\t\t\t\t\taffectsData: false,\n\t\t\t\t\t\trange\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Hides the fake visual selection created in {@link #_showFakeVisualSelection}.\n\t *\n\t * @private\n\t */\n\t_hideFakeVisualSelection() {\n\t\tconst model = this.editor.model;\n\n\t\tif ( model.markers.has( VISUAL_SELECTION_MARKER_NAME ) ) {\n\t\t\tmodel.change( writer => {\n\t\t\t\twriter.removeMarker( VISUAL_SELECTION_MARKER_NAME );\n\t\t\t} );\n\t\t}\n\t}\n}\n\n// Returns a link element if there's one among the ancestors of the provided `Position`.\n//\n// @private\n// @param {module:engine/view/position~Position} View position to analyze.\n// @returns {module:engine/view/attributeelement~AttributeElement|null} Link element at the position or null.\nfunction findLinkElementAncestor( position ) {\n\treturn position.getAncestors().find( ancestor => isLinkElement( ancestor ) );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module link/autolink\n */\n\nimport { Plugin } from 'ckeditor5/src/core';\nimport { TextWatcher, getLastTextLine } from 'ckeditor5/src/typing';\n\nimport { addLinkProtocolIfApplicable } from './utils';\n\nconst MIN_LINK_LENGTH_WITH_SPACE_AT_END = 4; // Ie: \"t.co \" (length 5).\n\n// This was a tweak from https://gist.github.com/dperini/729294.\nconst URL_REG_EXP = new RegExp(\n\t// Group 1: Line start or after a space.\n\t'(^|\\\\s)' +\n\t// Group 2: Detected URL (or e-mail).\n\t'(' +\n\t\t// Protocol identifier or short syntax \"//\"\n\t\t// a. Full form http://user@foo.bar.baz:8080/foo/bar.html#baz?foo=bar\n\t\t'(' +\n\t\t\t'(?:(?:(?:https?|ftp):)?\\\\/\\\\/)' +\n\t\t\t// BasicAuth using user:pass (optional)\n\t\t\t'(?:\\\\S+(?::\\\\S*)?@)?' +\n\t\t\t'(?:' +\n\t\t\t\t// IP address dotted notation octets\n\t\t\t\t// excludes loopback network 0.0.0.0\n\t\t\t\t// excludes reserved space >= 224.0.0.0\n\t\t\t\t// excludes network & broadcast addresses\n\t\t\t\t// (first & last IP address of each class)\n\t\t\t\t'(?:[1-9]\\\\d?|1\\\\d\\\\d|2[01]\\\\d|22[0-3])' +\n\t\t\t\t'(?:\\\\.(?:1?\\\\d{1,2}|2[0-4]\\\\d|25[0-5])){2}' +\n\t\t\t\t'(?:\\\\.(?:[1-9]\\\\d?|1\\\\d\\\\d|2[0-4]\\\\d|25[0-4]))' +\n\t\t\t\t'|' +\n\t\t\t\t'(' +\n\t\t\t\t\t// Do not allow `www.foo` - see https://github.com/ckeditor/ckeditor5/issues/8050.\n\t\t\t\t\t'((?!www\\\\.)|(www\\\\.))' +\n\t\t\t\t\t// Host & domain names.\n\t\t\t\t\t'(?![-_])(?:[-\\\\w\\\\u00a1-\\\\uffff]{0,63}[^-_]\\\\.)+' +\n\t\t\t\t\t// TLD identifier name.\n\t\t\t\t\t'(?:[a-z\\\\u00a1-\\\\uffff]{2,})' +\n\t\t\t\t')' +\n\t\t\t')' +\n\t\t\t// port number (optional)\n\t\t\t'(?::\\\\d{2,5})?' +\n\t\t\t// resource path (optional)\n\t\t\t'(?:[/?#]\\\\S*)?' +\n\t\t')' +\n\t\t'|' +\n\t\t// b. Short form (either www.example.com or example@example.com)\n\t\t'(' +\n\t\t\t'(www.|(\\\\S+@))' +\n\t\t\t// Host & domain names.\n\t\t\t'((?![-_])(?:[-\\\\w\\\\u00a1-\\\\uffff]{0,63}[^-_]\\\\.))+' +\n\t\t\t// TLD identifier name.\n\t\t\t'(?:[a-z\\\\u00a1-\\\\uffff]{2,})' +\n\t\t')' +\n\t')$', 'i' );\n\nconst URL_GROUP_IN_MATCH = 2;\n\n/**\n * The autolink plugin.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class AutoLink extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'AutoLink';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst selection = editor.model.document.selection;\n\n\t\tselection.on( 'change:range', () => {\n\t\t\t// Disable plugin when selection is inside a code block.\n\t\t\tthis.isEnabled = !selection.anchor.parent.is( 'element', 'codeBlock' );\n\t\t} );\n\n\t\tthis._enableTypingHandling();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tafterInit() {\n\t\tthis._enableEnterHandling();\n\t\tthis._enableShiftEnterHandling();\n\t}\n\n\t/**\n\t * Enables autolinking on typing.\n\t *\n\t * @private\n\t */\n\t_enableTypingHandling() {\n\t\tconst editor = this.editor;\n\n\t\tconst watcher = new TextWatcher( editor.model, text => {\n\t\t\t// 1. Detect Space after a text with a potential link.\n\t\t\tif ( !isSingleSpaceAtTheEnd( text ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// 2. Check text before last typed Space.\n\t\t\tconst url = getUrlAtTextEnd( text.substr( 0, text.length - 1 ) );\n\n\t\t\tif ( url ) {\n\t\t\t\treturn { url };\n\t\t\t}\n\t\t} );\n\n\t\tconst input = editor.plugins.get( 'Input' );\n\n\t\twatcher.on( 'matched:data', ( evt, data ) => {\n\t\t\tconst { batch, range, url } = data;\n\n\t\t\tif ( !input.isInput( batch ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst linkEnd = range.end.getShiftedBy( -1 ); // Executed after a space character.\n\t\t\tconst linkStart = linkEnd.getShiftedBy( -url.length );\n\n\t\t\tconst linkRange = editor.model.createRange( linkStart, linkEnd );\n\n\t\t\tthis._applyAutoLink( url, linkRange );\n\t\t} );\n\n\t\twatcher.bind( 'isEnabled' ).to( this );\n\t}\n\n\t/**\n\t * Enables autolinking on the Enter key.\n\t *\n\t * @private\n\t */\n\t_enableEnterHandling() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst enterCommand = editor.commands.get( 'enter' );\n\n\t\tif ( !enterCommand ) {\n\t\t\treturn;\n\t\t}\n\n\t\tenterCommand.on( 'execute', () => {\n\t\t\tconst position = model.document.selection.getFirstPosition();\n\n\t\t\tif ( !position.parent.previousSibling ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst rangeToCheck = model.createRangeIn( position.parent.previousSibling );\n\n\t\t\tthis._checkAndApplyAutoLinkOnRange( rangeToCheck );\n\t\t} );\n\t}\n\n\t/**\n\t * Enables autolinking on the Shift+Enter keyboard shortcut.\n\t *\n\t * @private\n\t */\n\t_enableShiftEnterHandling() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\n\t\tconst shiftEnterCommand = editor.commands.get( 'shiftEnter' );\n\n\t\tif ( !shiftEnterCommand ) {\n\t\t\treturn;\n\t\t}\n\n\t\tshiftEnterCommand.on( 'execute', () => {\n\t\t\tconst position = model.document.selection.getFirstPosition();\n\n\t\t\tconst rangeToCheck = model.createRange(\n\t\t\t\tmodel.createPositionAt( position.parent, 0 ),\n\t\t\t\tposition.getShiftedBy( -1 )\n\t\t\t);\n\n\t\t\tthis._checkAndApplyAutoLinkOnRange( rangeToCheck );\n\t\t} );\n\t}\n\n\t/**\n\t * Checks if the passed range contains a linkable text.\n\t *\n\t * @param {module:engine/model/range~Range} rangeToCheck\n\t * @private\n\t */\n\t_checkAndApplyAutoLinkOnRange( rangeToCheck ) {\n\t\tconst model = this.editor.model;\n\t\tconst { text, range } = getLastTextLine( rangeToCheck, model );\n\n\t\tconst url = getUrlAtTextEnd( text );\n\n\t\tif ( url ) {\n\t\t\tconst linkRange = model.createRange(\n\t\t\t\trange.end.getShiftedBy( -url.length ),\n\t\t\t\trange.end\n\t\t\t);\n\n\t\t\tthis._applyAutoLink( url, linkRange );\n\t\t}\n\t}\n\n\t/**\n\t * Applies a link on a given range.\n\t *\n\t * @param {String} url The URL to link.\n\t * @param {module:engine/model/range~Range} range The text range to apply the link attribute to.\n\t * @private\n\t */\n\t_applyAutoLink( link, range ) {\n\t\tconst model = this.editor.model;\n\n\t\tif ( !this.isEnabled || !isLinkAllowedOnRange( range, model ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Enqueue change to make undo step.\n\t\tmodel.enqueueChange( writer => {\n\t\t\tconst defaultProtocol = this.editor.config.get( 'link.defaultProtocol' );\n\t\t\tconst parsedUrl = addLinkProtocolIfApplicable( link, defaultProtocol );\n\t\t\twriter.setAttribute( 'linkHref', parsedUrl, range );\n\t\t} );\n\t}\n}\n\n// Check if text should be evaluated by the plugin in order to reduce number of RegExp checks on whole text.\nfunction isSingleSpaceAtTheEnd( text ) {\n\treturn text.length > MIN_LINK_LENGTH_WITH_SPACE_AT_END && text[ text.length - 1 ] === ' ' && text[ text.length - 2 ] !== ' ';\n}\n\nfunction getUrlAtTextEnd( text ) {\n\tconst match = URL_REG_EXP.exec( text );\n\n\treturn match ? match[ URL_GROUP_IN_MATCH ] : null;\n}\n\nfunction isLinkAllowedOnRange( range, model ) {\n\treturn model.schema.checkAttributeInSelection( model.createSelection( range ), 'linkHref' );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module link/link\n */\n\nimport { Plugin } from 'ckeditor5/src/core';\nimport LinkEditing from './linkediting';\nimport LinkUI from './linkui';\nimport AutoLink from './autolink';\n\n/**\n * The link plugin.\n *\n * This is a \"glue\" plugin that loads the {@link module:link/linkediting~LinkEditing link editing feature}\n * and {@link module:link/linkui~LinkUI link UI feature}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Link extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ LinkEditing, LinkUI, AutoLink ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Link';\n\t}\n}\n\n/**\n * The configuration of the {@link module:link/link~Link} feature.\n *\n * Read more in {@link module:link/link~LinkConfig}.\n *\n * @member {module:link/link~LinkConfig} module:core/editor/editorconfig~EditorConfig#link\n */\n\n/**\n * The configuration of the {@link module:link/link~Link link feature}.\n *\n *\t\tClassicEditor\n *\t\t\t.create( editorElement, {\n * \t\t\t\tlink: ... // Link feature configuration.\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * See {@link module:core/editor/editorconfig~EditorConfig all editor options}.\n * @interface LinkConfig\n */\n\n/**\n * When set, the editor will add the given protocol to the link when the user creates a link without one.\n * For example, when the user is creating a link and types `ckeditor.com` in the link form input, during link submission\n * the editor will automatically add the `http://` protocol, so the link will look as follows: `http://ckeditor.com`.\n *\n * The feature also provides email address auto-detection. When you submit `hello@example.com`,\n * the plugin will automatically change it to `mailto:hello@example.com`.\n *\n * \t\tClassicEditor\n *\t\t\t.create( editorElement, {\n * \t\t\t\tlink: {\n * \t\t\t\t\tdefaultProtocol: 'http://'\n * \t\t\t\t}\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * **NOTE:** If no configuration is provided, the editor will not auto-fix the links.\n *\n * @member {String} module:link/link~LinkConfig#defaultProtocol\n */\n\n/**\n * When set to `true`, the `target=\"blank\"` and `rel=\"noopener noreferrer\"` attributes are automatically added to all external links\n * in the editor. \"External links\" are all links in the editor content starting with `http`, `https`, or `//`.\n *\n *\t\tClassicEditor\n *\t\t\t.create( editorElement, {\n *\t\t\t\tlink: {\n *\t\t\t\t\taddTargetToExternalLinks: true\n *\t\t\t\t}\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * Internally, this option activates a predefined {@link module:link/link~LinkConfig#decorators automatic link decorator}\n * that extends all external links with the `target` and `rel` attributes.\n *\n * **Note**: To control the `target` and `rel` attributes of specific links in the edited content, a dedicated\n * {@link module:link/link~LinkDecoratorManualDefinition manual} decorator must be defined in the\n * {@link module:link/link~LinkConfig#decorators `config.link.decorators`} array. In such scenario,\n * the `config.link.addTargetToExternalLinks` option should remain `undefined` or `false` to not interfere with the manual decorator.\n *\n * It is possible to add other {@link module:link/link~LinkDecoratorAutomaticDefinition automatic}\n * or {@link module:link/link~LinkDecoratorManualDefinition manual} link decorators when this option is active.\n *\n * More information about decorators can be found in the {@link module:link/link~LinkConfig#decorators decorators configuration}\n * reference.\n *\n * @default false\n * @member {Boolean} module:link/link~LinkConfig#addTargetToExternalLinks\n */\n\n/**\n * Decorators provide an easy way to configure and manage additional link attributes in the editor content. There are\n * two types of link decorators:\n *\n * * {@link module:link/link~LinkDecoratorAutomaticDefinition Automatic} – They match links against pre–defined rules and\n * manage their attributes based on the results.\n * * {@link module:link/link~LinkDecoratorManualDefinition Manual} – They allow users to control link attributes individually,\n * using the editor UI.\n *\n * Link decorators are defined as objects with key-value pairs, where the key is the name provided for a given decorator and the\n * value is the decorator definition.\n *\n * The name of the decorator also corresponds to the {@glink framework/guides/architecture/editing-engine#text-attributes text attribute}\n * in the model. For instance, the `isExternal` decorator below is represented as a `linkIsExternal` attribute in the model.\n *\n *\t\tClassicEditor\n *\t\t\t.create( editorElement, {\n *\t\t\t\tlink: {\n *\t\t\t\t\tdecorators: {\n *\t\t\t\t\t\tisExternal: {\n *\t\t\t\t\t\t\tmode: 'automatic',\n *\t\t\t\t\t\t\tcallback: url => url.startsWith( 'http://' ),\n *\t\t\t\t\t\t\tattributes: {\n *\t\t\t\t\t\t\t\ttarget: '_blank',\n *\t\t\t\t\t\t\t\trel: 'noopener noreferrer'\n *\t\t\t\t\t\t\t}\n *\t\t\t\t\t\t},\n *\t\t\t\t\t\tisDownloadable: {\n *\t\t\t\t\t\t\tmode: 'manual',\n *\t\t\t\t\t\t\tlabel: 'Downloadable',\n *\t\t\t\t\t\t\tattributes: {\n *\t\t\t\t\t\t\t\tdownload: 'file.png',\n *\t\t\t\t\t\t\t}\n *\t\t\t\t\t\t},\n *\t\t\t\t\t\t// ...\n *\t\t\t\t\t}\n *\t\t\t\t}\n *\t\t\t} )\n *\t\t\t.then( ... )\n *\t\t\t.catch( ... );\n *\n * To learn more about the configuration syntax, check out the {@link module:link/link~LinkDecoratorAutomaticDefinition automatic}\n * and {@link module:link/link~LinkDecoratorManualDefinition manual} decorator option reference.\n *\n * **Warning:** Currently, link decorators work independently of one another and no conflict resolution mechanism exists.\n * For example, configuring the `target` attribute using both an automatic and a manual decorator at the same time could end up with\n * quirky results. The same applies if multiple manual or automatic decorators were defined for the same attribute.\n *\n * **Note**: Since the `target` attribute management for external links is a common use case, there is a predefined automatic decorator\n * dedicated for that purpose which can be enabled by turning a single option on. Check out the\n * {@link module:link/link~LinkConfig#addTargetToExternalLinks `config.link.addTargetToExternalLinks`}\n * configuration description to learn more.\n *\n * See also the {@glink features/link#custom-link-attributes-decorators link feature guide} for more information.\n *\n * @member {Object.} module:link/link~LinkConfig#decorators\n */\n\n/**\n * A link decorator definition. Two types implement this defition:\n *\n * * {@link module:link/link~LinkDecoratorManualDefinition}\n * * {@link module:link/link~LinkDecoratorAutomaticDefinition}\n *\n * Refer to their document for more information about available options or to the\n * {@glink features/link#custom-link-attributes-decorators link feature guide} for general information.\n *\n * @interface LinkDecoratorDefinition\n */\n\n/**\n * Link decorator type.\n *\n * Check out the {@glink features/link#custom-link-attributes-decorators link feature guide} for more information.\n *\n * @member {'manual'|'automatic'} module:link/link~LinkDecoratorDefinition#mode\n */\n\n/**\n * Describes an automatic {@link module:link/link~LinkConfig#decorators link decorator}. This decorator type matches\n * all links in the editor content against a function that decides whether the link should receive a pre–defined set of attributes.\n *\n * It takes an object with key-value pairs of attributes and a callback function that must return a Boolean value based on the link's\n * `href` (URL). When the callback returns `true`, attributes are applied to the link.\n *\n * For example, to add the `target=\"_blank\"` attribute to all links in the editor starting with `http://`, the\n * configuration could look like this:\n *\n *\t\t{\n *\t\t\tmode: 'automatic',\n *\t\t\tcallback: url => url.startsWith( 'http://' ),\n *\t\t\tattributes: {\n *\t\t\t\ttarget: '_blank'\n *\t\t\t}\n *\t\t}\n *\n * **Note**: Since the `target` attribute management for external links is a common use case, there is a predefined automatic decorator\n * dedicated for that purpose that can be enabled by turning a single option on. Check out the\n * {@link module:link/link~LinkConfig#addTargetToExternalLinks `config.link.addTargetToExternalLinks`}\n * configuration description to learn more.\n *\n * @typedef {Object} module:link/link~LinkDecoratorAutomaticDefinition\n * @property {'automatic'} mode Link decorator type. It is `'automatic'` for all automatic decorators.\n * @property {Function} callback Takes a `url` as a parameter and returns `true` if the `attributes` should be applied to the link.\n * @property {Object} attributes Key-value pairs used as link attributes added to the output during the\n * {@glink framework/guides/architecture/editing-engine#conversion downcasting}.\n * Attributes should follow the {@link module:engine/view/elementdefinition~ElementDefinition} syntax.\n */\n\n/**\n * Describes a manual {@link module:link/link~LinkConfig#decorators link decorator}. This decorator type is represented in\n * the link feature's {@link module:link/linkui user interface} as a switch that the user can use to control the presence\n * of a predefined set of attributes.\n *\n * For instance, to allow the users to manually control the presence of the `target=\"_blank\"` and\n * `rel=\"noopener noreferrer\"` attributes on specific links, the decorator could look as follows:\n *\n *\t\t{\n *\t\t\tmode: 'manual',\n *\t\t\tlabel: 'Open in a new tab',\n *\t\t\tdefaultValue: true,\n *\t\t\tattributes: {\n *\t\t\t\ttarget: '_blank',\n *\t\t\t\trel: 'noopener noreferrer'\n *\t\t\t}\n *\t\t}\n *\n * @typedef {Object} module:link/link~LinkDecoratorManualDefinition\n * @property {'manual'} mode Link decorator type. It is `'manual'` for all manual decorators.\n * @property {String} label The label of the UI button that the user can use to control the presence of link attributes.\n * @property {Object} attributes Key-value pairs used as link attributes added to the output during the\n * {@glink framework/guides/architecture/editing-engine#conversion downcasting}.\n * Attributes should follow the {@link module:engine/view/elementdefinition~ElementDefinition} syntax.\n * @property {Boolean} [defaultValue] Controls whether the decorator is \"on\" by default.\n */\n"],"sourceRoot":""}