@ckeditor/ckeditor5-link
Advanced tools
Comparing version 18.0.0 to 19.0.0
Changelog | ||
========= | ||
## [19.0.0](https://github.com/ckeditor/ckeditor5-link/compare/v18.0.0...v19.0.0) (2020-04-29) | ||
### Features | ||
* Introduced the `defaultValue` option to allow enabling a particular manual decorator by default. Closes [ckeditor/ckeditor5#6031](https://github.com/ckeditor/ckeditor5/issues/6031). ([82f966e](https://github.com/ckeditor/ckeditor5-link/commit/82f966e)) | ||
* After pasting a link the selection is now moved outside of a link to improve UX. This is done by change in the `Model#insertContent()` handling. Closes [ckeditor/ckeditor5#6053](https://github.com/ckeditor/ckeditor5/issues/6053). ([afabf03](https://github.com/ckeditor/ckeditor5-link/commit/afabf03)) | ||
### Other changes | ||
* Replaced `LabeledInputView` with `LabeledFieldView`. See [ckeditor/ckeditor5#6110](https://github.com/ckeditor/ckeditor5/issues/6110). ([e4e9ba9](https://github.com/ckeditor/ckeditor5-link/commit/e4e9ba9)) | ||
* Updated translations. ([00c5a5c](https://github.com/ckeditor/ckeditor5-link/commit/00c5a5c)) | ||
## [18.0.0](https://github.com/ckeditor/ckeditor5-link/compare/v17.0.0...v18.0.0) (2020-03-19) | ||
@@ -5,0 +18,0 @@ |
{ | ||
"name": "@ckeditor/ckeditor5-link", | ||
"version": "18.0.0", | ||
"version": "19.0.0", | ||
"description": "Link feature for CKEditor 5.", | ||
@@ -13,17 +13,17 @@ "keywords": [ | ||
"dependencies": { | ||
"@ckeditor/ckeditor5-core": "^18.0.0", | ||
"@ckeditor/ckeditor5-engine": "^18.0.0", | ||
"@ckeditor/ckeditor5-ui": "^18.0.0", | ||
"@ckeditor/ckeditor5-core": "^19.0.0", | ||
"@ckeditor/ckeditor5-engine": "^19.0.0", | ||
"@ckeditor/ckeditor5-ui": "^19.0.0", | ||
"lodash-es": "^4.17.10" | ||
}, | ||
"devDependencies": { | ||
"@ckeditor/ckeditor5-block-quote": "^18.0.0", | ||
"@ckeditor/ckeditor5-clipboard": "^18.0.0", | ||
"@ckeditor/ckeditor5-editor-classic": "^18.0.0", | ||
"@ckeditor/ckeditor5-enter": "^18.0.0", | ||
"@ckeditor/ckeditor5-paragraph": "^18.0.0", | ||
"@ckeditor/ckeditor5-theme-lark": "^18.0.0", | ||
"@ckeditor/ckeditor5-typing": "^18.0.0", | ||
"@ckeditor/ckeditor5-undo": "^18.0.0", | ||
"@ckeditor/ckeditor5-utils": "^18.0.0", | ||
"@ckeditor/ckeditor5-block-quote": "^19.0.0", | ||
"@ckeditor/ckeditor5-clipboard": "^19.0.0", | ||
"@ckeditor/ckeditor5-editor-classic": "^19.0.0", | ||
"@ckeditor/ckeditor5-enter": "^19.0.0", | ||
"@ckeditor/ckeditor5-paragraph": "^19.0.0", | ||
"@ckeditor/ckeditor5-theme-lark": "^19.0.0", | ||
"@ckeditor/ckeditor5-typing": "^19.0.0", | ||
"@ckeditor/ckeditor5-undo": "^19.0.0", | ||
"@ckeditor/ckeditor5-utils": "^19.0.0", | ||
"eslint": "^5.5.0", | ||
@@ -30,0 +30,0 @@ "eslint-config-ckeditor5": "^2.0.0", |
@@ -150,5 +150,10 @@ /** | ||
/** | ||
* Represents a link decorator definition ({@link module:link/link~LinkDecoratorManualDefinition `'manual'`} | ||
* or {@link module:link/link~LinkDecoratorAutomaticDefinition `'automatic'`}). | ||
* A link decorator definition. Two types implement this defition: | ||
* | ||
* * {@link module:link/link~LinkDecoratorManualDefinition} | ||
* * {@link module:link/link~LinkDecoratorAutomaticDefinition} | ||
* | ||
* Refer to their document for more information about available options or to the | ||
* {@glink features/link#custom-link-attributes-decorators link feature guide} for general information. | ||
* | ||
* @interface LinkDecoratorDefinition | ||
@@ -207,2 +212,3 @@ */ | ||
* label: 'Open in a new tab', | ||
* defaultValue: true, | ||
* attributes: { | ||
@@ -220,2 +226,3 @@ * target: '_blank', | ||
* Attributes should follow the {@link module:engine/view/elementdefinition~ElementDefinition} syntax. | ||
* @property {Boolean} [defaultValue] Controls whether the decorator is "on" by default. | ||
*/ |
@@ -217,4 +217,4 @@ /** | ||
const doc = this.editor.model.document; | ||
return doc.selection.getAttribute( decoratorName ) || false; | ||
return doc.selection.getAttribute( decoratorName ); | ||
} | ||
} |
@@ -104,2 +104,5 @@ /** | ||
this._setupLinkHighlight(); | ||
// Change the attributes of the selection in certain situations after the link was inserted into the document. | ||
this._enableInsertContentSelectionAttributesFixer(); | ||
} | ||
@@ -254,2 +257,96 @@ | ||
} | ||
/** | ||
* Starts listening to {@link module:engine/model/model~Model#event:insertContent} and corrects the model | ||
* selection attributes if the selection is at the end of a link after inserting the content. | ||
* | ||
* The purpose of this action is to improve the overall UX because the user is no longer "trapped" by the | ||
* `linkHref` attribute of the selection and they can type a "clean" (`linkHref`–less) text right away. | ||
* | ||
* See https://github.com/ckeditor/ckeditor5/issues/6053. | ||
* | ||
* @private | ||
*/ | ||
_enableInsertContentSelectionAttributesFixer() { | ||
const editor = this.editor; | ||
const model = editor.model; | ||
const selection = model.document.selection; | ||
model.on( 'insertContent', () => { | ||
const nodeBefore = selection.anchor.nodeBefore; | ||
const nodeAfter = selection.anchor.nodeAfter; | ||
// NOTE: ↰ and ↱ represent the gravity of the selection. | ||
// The only truly valid case is: | ||
// | ||
// ↰ | ||
// ...<$text linkHref="foo">INSERTED[]</$text> | ||
// | ||
// If the selection is not "trapped" by the `linkHref` attribute after inserting, there's nothing | ||
// to fix there. | ||
if ( !selection.hasAttribute( 'linkHref' ) ) { | ||
return; | ||
} | ||
// Filter out the following case where a link with the same href (e.g. <a href="foo">INSERTED</a>) is inserted | ||
// in the middle of an existing link: | ||
// | ||
// Before insertion: | ||
// ↰ | ||
// <$text linkHref="foo">l[]ink</$text> | ||
// | ||
// Expected after insertion: | ||
// ↰ | ||
// <$text linkHref="foo">lINSERTED[]ink</$text> | ||
// | ||
if ( !nodeBefore ) { | ||
return; | ||
} | ||
// Filter out the following case where the selection has the "linkHref" attribute because the | ||
// gravity is overridden and some text with another attribute (e.g. <b>INSERTED</b>) is inserted: | ||
// | ||
// Before insertion: | ||
// | ||
// ↱ | ||
// <$text linkHref="foo">[]link</$text> | ||
// | ||
// Expected after insertion: | ||
// | ||
// ↱ | ||
// <$text bold="true">INSERTED</$text><$text linkHref="foo">[]link</$text> | ||
// | ||
if ( !nodeBefore.hasAttribute( 'linkHref' ) ) { | ||
return; | ||
} | ||
// Filter out the following case where a link is a inserted in the middle (or before) another link | ||
// (different URLs, so they will not merge). In this (let's say weird) case, we can leave the selection | ||
// attributes as they are because the user will end up writing in one link or another anyway. | ||
// | ||
// Before insertion: | ||
// | ||
// ↰ | ||
// <$text linkHref="foo">l[]ink</$text> | ||
// | ||
// Expected after insertion: | ||
// | ||
// ↰ | ||
// <$text linkHref="foo">l</$text><$text linkHref="bar">INSERTED[]</$text><$text linkHref="foo">ink</$text> | ||
// | ||
if ( nodeAfter && nodeAfter.hasAttribute( 'linkHref' ) ) { | ||
return; | ||
} | ||
// Make the selection free of link-related model attributes. | ||
// All link-related model attributes start with "link". That includes not only "linkHref" | ||
// but also all decorator attributes (they have dynamic names). | ||
model.change( writer => { | ||
[ ...model.document.selection.getAttributeKeys() ] | ||
.filter( name => name.startsWith( 'link' ) ) | ||
.forEach( name => writer.removeSelectionAttribute( name ) ); | ||
} ); | ||
}, { priority: 'low' } ); | ||
} | ||
} |
@@ -147,5 +147,5 @@ /** | ||
const formView = new LinkFormView( editor.locale, linkCommand.manualDecorators ); | ||
const formView = new LinkFormView( editor.locale, linkCommand ); | ||
formView.urlInputView.bind( 'value' ).to( linkCommand, 'value' ); | ||
formView.urlInputView.fieldView.bind( 'value' ).to( linkCommand, 'value' ); | ||
@@ -158,3 +158,3 @@ // Form elements should be read-only when corresponding commands are disabled. | ||
this.listenTo( formView, 'submit', () => { | ||
editor.execute( 'link', formView.urlInputView.inputView.element.value, formView.getDecoratorSwitchesState() ); | ||
editor.execute( 'link', formView.urlInputView.fieldView.element.value, formView.getDecoratorSwitchesState() ); | ||
this._closeFormView(); | ||
@@ -190,3 +190,3 @@ } ); | ||
editor.keystrokes.set( linkKeystroke, ( keyEvtData, cancel ) => { | ||
// Prevent focusing the search bar in FF and opening new tab in Edge. #153, #154. | ||
// Prevent focusing the search bar in FF, Chrome and Edge. See https://github.com/ckeditor/ckeditor5/issues/4811. | ||
cancel(); | ||
@@ -304,7 +304,7 @@ | ||
if ( this._balloon.visibleView === this.formView ) { | ||
this.formView.urlInputView.select(); | ||
this.formView.urlInputView.fieldView.select(); | ||
} | ||
// Make sure that each time the panel shows up, the URL field remains in sync with the value of | ||
// the command. If the user typed in the input, then canceled the balloon (`urlInputView#value` stays | ||
// the command. If the user typed in the input, then canceled the balloon (`urlInputView.fieldView#value` stays | ||
// unaltered) and re-opened it without changing the value of the link command (e.g. because they | ||
@@ -314,3 +314,3 @@ // clicked the same link), they would see the old value instead of the actual value of the command. | ||
// https://github.com/ckeditor/ckeditor5-link/issues/123 | ||
this.formView.urlInputView.inputView.element.value = linkCommand.value || ''; | ||
this.formView.urlInputView.fieldView.element.value = linkCommand.value || ''; | ||
} | ||
@@ -317,0 +317,0 @@ |
@@ -15,5 +15,6 @@ /** | ||
import SwitchButtonView from '@ckeditor/ckeditor5-ui/src/button/switchbuttonview'; | ||
import LabeledInputView from '@ckeditor/ckeditor5-ui/src/labeledinput/labeledinputview'; | ||
import InputTextView from '@ckeditor/ckeditor5-ui/src/inputtext/inputtextview'; | ||
import LabeledFieldView from '@ckeditor/ckeditor5-ui/src/labeledfield/labeledfieldview'; | ||
import { createLabeledInputText } from '@ckeditor/ckeditor5-ui/src/labeledfield/utils'; | ||
import submitHandler from '@ckeditor/ckeditor5-ui/src/bindings/submithandler'; | ||
@@ -42,6 +43,5 @@ import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker'; | ||
* @param {module:utils/locale~Locale} [locale] The localization services instance. | ||
* @param {module:utils/collection~Collection} [manualDecorators] Reference to manual decorators in | ||
* {@link module:link/linkcommand~LinkCommand#manualDecorators}. | ||
* @param {module:link/linkcommand~LinkCommand} linkCommand Reference to {@link module:link/linkcommand~LinkCommand}. | ||
*/ | ||
constructor( locale, manualDecorators = [] ) { | ||
constructor( locale, linkCommand ) { | ||
super( locale ); | ||
@@ -70,3 +70,3 @@ | ||
* | ||
* @member {module:ui/labeledinput/labeledinputview~LabeledInputView} | ||
* @member {module:ui/labeledfield/labeledfieldview~LabeledFieldView} | ||
*/ | ||
@@ -99,3 +99,3 @@ this.urlInputView = this._createUrlInput(); | ||
*/ | ||
this._manualDecoratorSwitches = this._createManualDecoratorSwitches( manualDecorators ); | ||
this._manualDecoratorSwitches = this._createManualDecoratorSwitches( linkCommand ); | ||
@@ -108,3 +108,3 @@ /** | ||
*/ | ||
this.children = this._createFormChildren( manualDecorators ); | ||
this.children = this._createFormChildren( linkCommand.manualDecorators ); | ||
@@ -142,3 +142,3 @@ /** | ||
if ( manualDecorators.length ) { | ||
if ( linkCommand.manualDecorators.length ) { | ||
classList.push( 'ck-link-form_layout-vertical' ); | ||
@@ -216,3 +216,3 @@ } | ||
* @private | ||
* @returns {module:ui/labeledinput/labeledinputview~LabeledInputView} Labeled input view instance. | ||
* @returns {module:ui/labeledfield/labeledfieldview~LabeledFieldView} Labeled field view instance. | ||
*/ | ||
@@ -222,6 +222,6 @@ _createUrlInput() { | ||
const labeledInput = new LabeledInputView( this.locale, InputTextView ); | ||
const labeledInput = new LabeledFieldView( this.locale, createLabeledInputText ); | ||
labeledInput.label = t( 'Link URL' ); | ||
labeledInput.inputView.placeholder = 'https://example.com'; | ||
labeledInput.fieldView.placeholder = 'https://example.com'; | ||
@@ -268,10 +268,9 @@ return labeledInput; | ||
* @private | ||
* @param {module:utils/collection~Collection} manualDecorators A reference to the | ||
* collection of manual decorators stored in the link command. | ||
* @param {module:link/linkcommand~LinkCommand} linkCommand A reference to the link command. | ||
* @returns {module:ui/viewcollection~ViewCollection} of switch buttons. | ||
*/ | ||
_createManualDecoratorSwitches( manualDecorators ) { | ||
_createManualDecoratorSwitches( linkCommand ) { | ||
const switches = this.createCollection(); | ||
for ( const manualDecorator of manualDecorators ) { | ||
for ( const manualDecorator of linkCommand.manualDecorators ) { | ||
const switchButton = new SwitchButtonView( this.locale ); | ||
@@ -285,3 +284,5 @@ | ||
switchButton.bind( 'isOn' ).to( manualDecorator, 'value' ); | ||
switchButton.bind( 'isOn' ).toMany( [ manualDecorator, linkCommand ], 'value', ( decoratorValue, commandValue ) => { | ||
return commandValue === undefined && decoratorValue === undefined ? manualDecorator.defaultValue : decoratorValue; | ||
} ); | ||
@@ -288,0 +289,0 @@ switchButton.on( 'execute', () => { |
@@ -30,4 +30,5 @@ /** | ||
* Attributes should keep the format of attributes defined in {@link module:engine/view/elementdefinition~ElementDefinition}. | ||
* @param {Boolean} [config.defaultValue] Controls whether the decorator is "on" by default. | ||
*/ | ||
constructor( { id, label, attributes } ) { | ||
constructor( { id, label, attributes, defaultValue } ) { | ||
/** | ||
@@ -49,2 +50,9 @@ * An ID of a manual decorator which is the name of the attribute in the model, for example: 'linkManualDecorator0'. | ||
/** | ||
* The default value of manual decorator. | ||
* | ||
* @type {Boolean} | ||
*/ | ||
this.defaultValue = defaultValue; | ||
/** | ||
* The label used in the user interface to toggle the manual decorator. | ||
@@ -51,0 +59,0 @@ * |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
190987
2134
+ Added@ckeditor/ckeditor5-core@19.0.1(transitive)
+ Added@ckeditor/ckeditor5-engine@19.0.1(transitive)
+ Added@ckeditor/ckeditor5-ui@19.0.1(transitive)
+ Added@ckeditor/ckeditor5-utils@19.0.2(transitive)
- Removed@ckeditor/ckeditor5-core@18.0.0(transitive)
- Removed@ckeditor/ckeditor5-engine@18.0.0(transitive)
- Removed@ckeditor/ckeditor5-ui@18.0.0(transitive)
- Removed@ckeditor/ckeditor5-utils@18.0.0(transitive)