From 7778ddc2925941ee5f3794091589c4d098374679 Mon Sep 17 00:00:00 2001 From: panr Date: Wed, 3 Jun 2020 17:09:07 +0200 Subject: [PATCH 01/15] Add manual test for link protocol. --- .../ckeditor5-link/tests/manual/protocol.html | 52 +++++++++++++++++++ .../ckeditor5-link/tests/manual/protocol.js | 49 +++++++++++++++++ .../ckeditor5-link/tests/manual/protocol.md | 8 +++ 3 files changed, 109 insertions(+) create mode 100644 packages/ckeditor5-link/tests/manual/protocol.html create mode 100644 packages/ckeditor5-link/tests/manual/protocol.js create mode 100644 packages/ckeditor5-link/tests/manual/protocol.md diff --git a/packages/ckeditor5-link/tests/manual/protocol.html b/packages/ckeditor5-link/tests/manual/protocol.html new file mode 100644 index 00000000000..5ea3e8230d9 --- /dev/null +++ b/packages/ckeditor5-link/tests/manual/protocol.html @@ -0,0 +1,52 @@ + + +

The default configuration for the link protocol has been set to .

+ +

...but you can change it:

+
+ + + + +
+ +
+

This is CKEditor5 from CKSource. If you need more information please contact us at support@example.com [1].

+
+ +

[1] Copy the email address and create a link with it (mailto: protocol will be added automatically).

diff --git a/packages/ckeditor5-link/tests/manual/protocol.js b/packages/ckeditor5-link/tests/manual/protocol.js new file mode 100644 index 00000000000..c99580b4256 --- /dev/null +++ b/packages/ckeditor5-link/tests/manual/protocol.js @@ -0,0 +1,49 @@ +/** + * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +/* globals console:false, window, document */ + +import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'; +import Enter from '@ckeditor/ckeditor5-enter/src/enter'; +import Typing from '@ckeditor/ckeditor5-typing/src/typing'; +import Link from '../../src/link'; +import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph'; +import Undo from '@ckeditor/ckeditor5-undo/src/undo'; +import Superscript from '@ckeditor/ckeditor5-basic-styles/src/superscript'; + +ClassicEditor + .create( document.querySelector( '#editor' ), { + plugins: [ Link, Typing, Paragraph, Undo, Enter, Superscript ], + toolbar: [ 'link', 'undo', 'redo' ], + link: { + addTargetToExternalLinks: true, + defaultProtocol: 'http://' + } + } ) + .then( editor => { + window.editor = editor; + + const LinkUIPlugin = editor.plugins.get( 'LinkUI' ); + const formView = LinkUIPlugin.formView; + const defaultProtocol = editor.config.get( 'link.defaultProtocol' ); + + document.getElementById( 'default-protocol' ).innerText = defaultProtocol; + + document.querySelectorAll( '#protocol-settings input[type="radio"]' ).forEach( radio => { + radio.checked = radio.value === defaultProtocol; + + radio.addEventListener( 'click', ( { + target: { value: protocol } + } ) => { + editor.config.set( 'link.defaultProtocol', protocol ); + + // Change input placeholder just for manual test's case to provide more dynamic behavior. + formView.urlInputView.fieldView.placeholder = protocol + 'example.com'; + } ); + } ); + } ) + .catch( err => { + console.error( err.stack ); + } ); diff --git a/packages/ckeditor5-link/tests/manual/protocol.md b/packages/ckeditor5-link/tests/manual/protocol.md new file mode 100644 index 00000000000..2a5266c561a --- /dev/null +++ b/packages/ckeditor5-link/tests/manual/protocol.md @@ -0,0 +1,8 @@ +## Link protocol + +This test checks whether: +- `config.link.defaultProtocol` applies. +- user is able to dynamically change the link protocol (just as an extended example of usage). +- the plugin dynamically change link protocol to `mailto:` when email address was detected. + +When you dynamically change the value of the link protocol, the form input placeholder should change as well. From 79a31afe5e5a2a662b5099c82de8dce3f2ec06a5 Mon Sep 17 00:00:00 2001 From: panr Date: Wed, 3 Jun 2020 17:10:46 +0200 Subject: [PATCH 02/15] Add default link protocol automatically. --- packages/ckeditor5-link/src/linkui.js | 16 +++++++++++++--- packages/ckeditor5-link/src/ui/linkformview.js | 13 ++++++++----- packages/ckeditor5-link/src/utils.js | 7 +++++++ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/packages/ckeditor5-link/src/linkui.js b/packages/ckeditor5-link/src/linkui.js index 68370115999..7318f3203f3 100644 --- a/packages/ckeditor5-link/src/linkui.js +++ b/packages/ckeditor5-link/src/linkui.js @@ -9,7 +9,7 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin'; import ClickObserver from '@ckeditor/ckeditor5-engine/src/view/observer/clickobserver'; -import { isLinkElement } from './utils'; +import { isLinkElement, DEFAULT_PROTOCOL } from './utils'; import ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon'; import clickOutsideHandler from '@ckeditor/ckeditor5-ui/src/bindings/clickoutsidehandler'; @@ -143,8 +143,9 @@ export default class LinkUI extends Plugin { _createFormView() { const editor = this.editor; const linkCommand = editor.commands.get( 'link' ); + const defaultProtocol = editor.config.get( 'link.defaultProtocol' ) || DEFAULT_PROTOCOL; - const formView = new LinkFormView( editor.locale, linkCommand ); + const formView = new LinkFormView( editor.locale, linkCommand, defaultProtocol ); formView.urlInputView.fieldView.bind( 'value' ).to( linkCommand, 'value' ); @@ -154,7 +155,16 @@ export default class LinkUI extends Plugin { // Execute link command after clicking the "Save" button. this.listenTo( formView, 'submit', () => { - editor.execute( 'link', formView.urlInputView.fieldView.element.value, formView.getDecoratorSwitchesState() ); + const { value } = formView.urlInputView.fieldView.element; + const hasProtocol = ( /\w+:\/\//gmi ).test( value ); + const isEmail = ( /[\w-]+@[\w-]+\.+[\w-]+/gmi ).test( value ); + + // It's good to check config second time on submit for more dynamic cases + // when protocol might change after the element rendered. + const protocol = isEmail && 'mailto:' || editor.config.get( 'link.defaultProtocol' ) || defaultProtocol; + const parsedValue = !hasProtocol && value ? protocol + value : value; + + editor.execute( 'link', parsedValue, formView.getDecoratorSwitchesState() ); this._closeFormView(); } ); diff --git a/packages/ckeditor5-link/src/ui/linkformview.js b/packages/ckeditor5-link/src/ui/linkformview.js index 2b050ee8e25..12fb97d865a 100644 --- a/packages/ckeditor5-link/src/ui/linkformview.js +++ b/packages/ckeditor5-link/src/ui/linkformview.js @@ -21,6 +21,8 @@ import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker'; import FocusCycler from '@ckeditor/ckeditor5-ui/src/focuscycler'; import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler'; +import { DEFAULT_PROTOCOL } from '../utils'; + import checkIcon from '@ckeditor/ckeditor5-core/theme/icons/check.svg'; import cancelIcon from '@ckeditor/ckeditor5-core/theme/icons/cancel.svg'; import '../../theme/linkform.css'; @@ -40,8 +42,9 @@ export default class LinkFormView extends View { * * @param {module:utils/locale~Locale} [locale] The localization services instance. * @param {module:link/linkcommand~LinkCommand} linkCommand Reference to {@link module:link/linkcommand~LinkCommand}. + * @param {String} [protocol] A value of a protocol to be displayed in the input's placeholder. */ - constructor( locale, linkCommand ) { + constructor( locale, linkCommand, protocol ) { super( locale ); const t = locale.t; @@ -67,7 +70,7 @@ export default class LinkFormView extends View { * * @member {module:ui/labeledfield/labeledfieldview~LabeledFieldView} */ - this.urlInputView = this._createUrlInput(); + this.urlInputView = this._createUrlInput( protocol ); /** * The Save button view. @@ -207,15 +210,15 @@ export default class LinkFormView extends View { * Creates a labeled input view. * * @private + * @param {module:link/utils~DefaultProtocol} [protocol=http://] A value of a protocol to be displayed in the input's placeholder. * @returns {module:ui/labeledfield/labeledfieldview~LabeledFieldView} Labeled field view instance. */ - _createUrlInput() { + _createUrlInput( protocol = DEFAULT_PROTOCOL ) { const t = this.locale.t; - const labeledInput = new LabeledFieldView( this.locale, createLabeledInputText ); labeledInput.label = t( 'Link URL' ); - labeledInput.fieldView.placeholder = 'https://example.com'; + labeledInput.fieldView.placeholder = protocol + 'example.com'; return labeledInput; } diff --git a/packages/ckeditor5-link/src/utils.js b/packages/ckeditor5-link/src/utils.js index 4c80d39e9c0..4eafb2be35a 100644 --- a/packages/ckeditor5-link/src/utils.js +++ b/packages/ckeditor5-link/src/utils.js @@ -12,6 +12,13 @@ import { upperFirst } from 'lodash-es'; const ATTRIBUTE_WHITESPACES = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g; // eslint-disable-line no-control-regex const SAFE_URL = /^(?:(?:https?|ftps?|mailto):|[^a-z]|[a-z+.-]+(?:[^a-z+.:-]|$))/i; +/** + * A default link protocol value. + * @typedef {String} module:link/utils~DefaultProtocol + * @default 'http://' + */ +export const DEFAULT_PROTOCOL = 'http://'; + /** * Returns `true` if a given view node is the link element. * From 96e8d9e5207a6d79ee628607da1da30edb834dc0 Mon Sep 17 00:00:00 2001 From: panr Date: Wed, 3 Jun 2020 17:11:04 +0200 Subject: [PATCH 03/15] Add tests for the link protocol. --- packages/ckeditor5-link/tests/linkui.js | 62 ++++++++++++++++++- .../ckeditor5-link/tests/ui/linkformview.js | 4 +- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/packages/ckeditor5-link/tests/linkui.js b/packages/ckeditor5-link/tests/linkui.js index 48c6b18f511..602320bcafc 100644 --- a/packages/ckeditor5-link/tests/linkui.js +++ b/packages/ckeditor5-link/tests/linkui.js @@ -8,7 +8,7 @@ import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor'; import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils'; import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard'; -import { setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; +import { setData as setModelData, getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view'; import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph'; @@ -21,6 +21,8 @@ import ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextu import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview'; import View from '@ckeditor/ckeditor5-ui/src/view'; +import { DEFAULT_PROTOCOL } from '../src/utils'; + import ClickObserver from '@ckeditor/ckeditor5-engine/src/view/observer/clickobserver'; describe( 'LinkUI', () => { @@ -905,6 +907,62 @@ describe( 'LinkUI', () => { expect( editor.ui.focusTracker.isFocused ).to.be.true; } ); + describe( 'link protocol', () => { + beforeEach( () => { + editor.model.schema.extend( '$text', { + allowIn: '$root', + allowAttributes: 'linkHref' + } ); + } ); + + it( 'should use a default link protocol from the `config.link.defaultProtocol` when provided', () => { + return ClassicTestEditor + .create( editorElement, { + link: { + defaultProtocol: 'https://' + } + } ) + .then( editor => { + const defaultProtocol = editor.config.get( 'link.defaultProtocol' ); + + expect( defaultProtocol ).to.equal( 'https://' ); + + editorElement.remove(); + editor.destroy(); + } ); + } ); + + it( 'should use `http://` as a default link protocol without any configuration', () => { + formView.urlInputView.fieldView.value = 'ckeditor.com'; + formView.fire( 'submit' ); + + expect( formView.urlInputView.fieldView.value ).to.equal( 'http://ckeditor.com' ); + } ); + + it( 'should propagate the protocol to the link\'s `linkHref` attribute in model', () => { + setModelData( editor.model, '[ckeditor.com]' ); + + formView.urlInputView.fieldView.value = 'ckeditor.com'; + formView.fire( 'submit' ); + + expect( getModelData( editor.model ) ).to.equal( + '[<$text linkHref="http://ckeditor.com">ckeditor.com]' + ); + } ); + + it( 'should detect an email on submitting the form and add "mailto:" protocol automatically to the provided value', () => { + setModelData( editor.model, '[email@example.com]' ); + + formView.urlInputView.fieldView.value = 'email@example.com'; + formView.fire( 'submit' ); + + expect( formView.urlInputView.fieldView.value ).to.equal( 'mailto:email@example.com' ); + expect( getModelData( editor.model ) ).to.equal( + '[<$text linkHref="mailto:email@example.com">email@example.com]' + ); + } ); + } ); + describe( 'binding', () => { beforeEach( () => { setModelData( editor.model, 'f[o]o' ); @@ -1062,7 +1120,7 @@ describe( 'LinkUI', () => { formView.fire( 'submit' ); expect( executeSpy.calledOnce ).to.be.true; - expect( executeSpy.calledWithExactly( 'link', 'url', { linkIsFoo: true } ) ).to.be.true; + expect( executeSpy.calledWithExactly( 'link', DEFAULT_PROTOCOL + 'url', { linkIsFoo: true } ) ).to.be.true; } ); it( 'should reset switch state when form view is closed', () => { diff --git a/packages/ckeditor5-link/tests/ui/linkformview.js b/packages/ckeditor5-link/tests/ui/linkformview.js index 402274d89c7..b4c511dec43 100644 --- a/packages/ckeditor5-link/tests/ui/linkformview.js +++ b/packages/ckeditor5-link/tests/ui/linkformview.js @@ -21,6 +21,8 @@ import Link from '../../src/link'; import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin'; import mix from '@ckeditor/ckeditor5-utils/src/mix'; +import { DEFAULT_PROTOCOL } from '../../src/utils'; + describe( 'LinkFormView', () => { let view; @@ -83,7 +85,7 @@ describe( 'LinkFormView', () => { describe( 'url input view', () => { it( 'has placeholder', () => { - expect( view.urlInputView.fieldView.placeholder ).to.equal( 'https://example.com' ); + expect( view.urlInputView.fieldView.placeholder ).to.equal( DEFAULT_PROTOCOL + 'example.com' ); } ); } ); From cd7f08cf4e57d50c9cd79afc374395dd89602211 Mon Sep 17 00:00:00 2001 From: panr Date: Wed, 3 Jun 2020 18:12:08 +0200 Subject: [PATCH 04/15] Add API docs. --- packages/ckeditor5-link/src/link.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/ckeditor5-link/src/link.js b/packages/ckeditor5-link/src/link.js index 2fa90aabe23..2c29edd5bc7 100644 --- a/packages/ckeditor5-link/src/link.js +++ b/packages/ckeditor5-link/src/link.js @@ -57,6 +57,25 @@ export default class Link extends Plugin { * @interface LinkConfig */ +/** + * When set, the editor will add the given protocol to the link when the user creates a link without one. + * In case no configuration is provided, the value defaults to `http://`. + * For example, when the user is creating a link and types `ckeditor.com` in the link form input — during link submission — + * the editor will automatically add the `http://` protocol, so the link will be as follows: `http://ckeditor.com`. + * + * ClassicEditor + * .create( editorElement, { + * link: { + * defaultProtocol: 'http://' + * } + * } ) + * .then( ... ) + * .catch( ... ); + * + * @default 'http://' + * @member {String} module:link/link~LinkConfig#defaultProtocol + */ + /** * When set to `true`, the `target="blank"` and `rel="noopener noreferrer"` attributes are automatically added to all external links * in the editor. "External links" are all links in the editor content starting with `http`, `https`, or `//`. From f3fa2f4961992f5fd363381d0991e99184e0a0f6 Mon Sep 17 00:00:00 2001 From: panr Date: Wed, 3 Jun 2020 18:15:24 +0200 Subject: [PATCH 05/15] Fix whitespaces. --- packages/ckeditor5-link/tests/manual/protocol.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ckeditor5-link/tests/manual/protocol.html b/packages/ckeditor5-link/tests/manual/protocol.html index 5ea3e8230d9..6b5a4bd693d 100644 --- a/packages/ckeditor5-link/tests/manual/protocol.html +++ b/packages/ckeditor5-link/tests/manual/protocol.html @@ -14,7 +14,7 @@ width: 14px; height: 14px; left: 1px; - top: 1px; + top: 1px; background: hsla(207, 87%, 55%, 0.5); border-radius: 50px; animation: pulse 2s linear infinite; From 08c8db327800a893cf7f13949ab3f7b27fcda5c6 Mon Sep 17 00:00:00 2001 From: panr Date: Thu, 4 Jun 2020 14:31:54 +0200 Subject: [PATCH 06/15] Update documentation (API, guide). --- packages/ckeditor5-link/docs/features/link.md | 24 +++++++++++++++++++ packages/ckeditor5-link/src/link.js | 7 ++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/ckeditor5-link/docs/features/link.md b/packages/ckeditor5-link/docs/features/link.md index 4aa62b8189d..66ecf68396d 100644 --- a/packages/ckeditor5-link/docs/features/link.md +++ b/packages/ckeditor5-link/docs/features/link.md @@ -147,6 +147,30 @@ ClassicEditor .catch( ... ); ``` +#### Adding default link protocol for the external links + +Default link protocol can be usefull when user forget to type a full URL address to an external source, site etc. Sometimes copying the text, like for example `ckeditor.com` and converting it to a link may cause some issues. When you do this, the created link will direct you to `yourdomain.com/ckeditor.com`, because you forgot to pass the right protocol which makes the link relative to the site where it appears. + +Enabling the `{@link module:link/link~LinkConfig#defaultProtocol config.link.defaultProtocol}`, the {@link module:link/link~Link} feature will handle this issue for you. By default it doesn't fix the passed link value, but when you set `{@link module:link/link~LinkConfig#defaultProtocol config.link.defaultProtocol}` to — for example — `http://`, the plugin will add the given protocol to the every link that may need it (like `ckeditor.com`, `example.com` etc. where `[protocol://]example.com` is missing). Here's the basic configuration example: + +```js +ClassicEditor + .create( document.querySelector( '#editor' ), { + // ... + link: { + defaultProtocol: 'http://' + } + } ) + .then( ... ) + .catch( ... ); +``` + + + Having `config.link.defaultProtocol` enabled you are still able to link things locally using `#` or `/`. Protocol won't be added to those links. + + Enabled feature also gives you an **email addresses auto-detection** feature. When you submit `hello@example.com`, the plugin will change it automatically to `mailto:hello@example.com`. + + #### Adding attributes to links based on pre–defined rules (automatic decorators) Automatic link decorators match all links in the editor content against a {@link module:link/link~LinkDecoratorAutomaticDefinition function} which decides whether the link should receive some set of attributes, considering the URL (`href`) of the link. These decorators work silently and are being applied during the {@link framework/guides/architecture/editing-engine#conversion data downcast} only. diff --git a/packages/ckeditor5-link/src/link.js b/packages/ckeditor5-link/src/link.js index 2c29edd5bc7..96f8e9f9897 100644 --- a/packages/ckeditor5-link/src/link.js +++ b/packages/ckeditor5-link/src/link.js @@ -59,10 +59,12 @@ export default class Link extends Plugin { /** * When set, the editor will add the given protocol to the link when the user creates a link without one. - * In case no configuration is provided, the value defaults to `http://`. * For example, when the user is creating a link and types `ckeditor.com` in the link form input — during link submission — * the editor will automatically add the `http://` protocol, so the link will be as follows: `http://ckeditor.com`. * + * The feature also comes with an email auto-detection. When you submit `hello@example.com` + * the plugin will automatically change it to `mailto:hello@example.com`. + * * ClassicEditor * .create( editorElement, { * link: { @@ -72,7 +74,8 @@ export default class Link extends Plugin { * .then( ... ) * .catch( ... ); * - * @default 'http://' + * **NOTE:** In case no configuration is provided, the editor won't auto-fix the links. + * * @member {String} module:link/link~LinkConfig#defaultProtocol */ From e51d83e50c0f7cff804b3e5ae05414c3f30dcf00 Mon Sep 17 00:00:00 2001 From: panr Date: Thu, 4 Jun 2020 14:32:40 +0200 Subject: [PATCH 07/15] Change manual test. --- packages/ckeditor5-link/tests/manual/protocol.html | 6 +++--- packages/ckeditor5-link/tests/manual/protocol.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/ckeditor5-link/tests/manual/protocol.html b/packages/ckeditor5-link/tests/manual/protocol.html index 6b5a4bd693d..8ed4a7d7a4e 100644 --- a/packages/ckeditor5-link/tests/manual/protocol.html +++ b/packages/ckeditor5-link/tests/manual/protocol.html @@ -37,16 +37,16 @@

The default configuration for the link protocol has been set to .

-

...but you can change it:

+

...but you can dynamically change it:

+ -

This is CKEditor5 from CKSource. If you need more information please contact us at support@example.com [1].

-

[1] Copy the email address and create a link with it (mailto: protocol will be added automatically).

+

[1]When feature enabled: copy the email address and create a link with it (mailto: protocol will be added automatically).

diff --git a/packages/ckeditor5-link/tests/manual/protocol.js b/packages/ckeditor5-link/tests/manual/protocol.js index c99580b4256..d2d75b0724a 100644 --- a/packages/ckeditor5-link/tests/manual/protocol.js +++ b/packages/ckeditor5-link/tests/manual/protocol.js @@ -37,10 +37,10 @@ ClassicEditor radio.addEventListener( 'click', ( { target: { value: protocol } } ) => { - editor.config.set( 'link.defaultProtocol', protocol ); + editor.config.set( 'link.defaultProtocol', protocol === 'none' ? undefined : protocol ); // Change input placeholder just for manual test's case to provide more dynamic behavior. - formView.urlInputView.fieldView.placeholder = protocol + 'example.com'; + formView.urlInputView.fieldView.placeholder = protocol === 'none' ? 'https://example.com' : protocol + 'example.com'; } ); } ); } ) From 3926be33a44c1c4ecad06c42ed50d55b7d3241a9 Mon Sep 17 00:00:00 2001 From: panr Date: Thu, 4 Jun 2020 14:33:53 +0200 Subject: [PATCH 08/15] Remove DEFAULT_PROTOCOL and fix the script for better handling link values. --- packages/ckeditor5-link/src/linkui.js | 13 ++-- .../ckeditor5-link/src/ui/linkformview.js | 6 +- packages/ckeditor5-link/src/utils.js | 7 -- packages/ckeditor5-link/tests/linkui.js | 65 +++++++++++++++++-- .../ckeditor5-link/tests/ui/linkformview.js | 4 +- 5 files changed, 72 insertions(+), 23 deletions(-) diff --git a/packages/ckeditor5-link/src/linkui.js b/packages/ckeditor5-link/src/linkui.js index 7318f3203f3..d74bc131bf1 100644 --- a/packages/ckeditor5-link/src/linkui.js +++ b/packages/ckeditor5-link/src/linkui.js @@ -9,7 +9,7 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin'; import ClickObserver from '@ckeditor/ckeditor5-engine/src/view/observer/clickobserver'; -import { isLinkElement, DEFAULT_PROTOCOL } from './utils'; +import { isLinkElement } from './utils'; import ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon'; import clickOutsideHandler from '@ckeditor/ckeditor5-ui/src/bindings/clickoutsidehandler'; @@ -143,7 +143,7 @@ export default class LinkUI extends Plugin { _createFormView() { const editor = this.editor; const linkCommand = editor.commands.get( 'link' ); - const defaultProtocol = editor.config.get( 'link.defaultProtocol' ) || DEFAULT_PROTOCOL; + const defaultProtocol = editor.config.get( 'link.defaultProtocol' ); const formView = new LinkFormView( editor.locale, linkCommand, defaultProtocol ); @@ -156,13 +156,16 @@ export default class LinkUI extends Plugin { // Execute link command after clicking the "Save" button. this.listenTo( formView, 'submit', () => { const { value } = formView.urlInputView.fieldView.element; - const hasProtocol = ( /\w+:\/\//gmi ).test( value ); + + const defaultProtocol = editor.config.get( 'link.defaultProtocol' ); + + const isProtocolNeeded = !!defaultProtocol && !( /^((\w+:(\/{2,})?)|(\W))/gmi ).test( value ); const isEmail = ( /[\w-]+@[\w-]+\.+[\w-]+/gmi ).test( value ); // It's good to check config second time on submit for more dynamic cases // when protocol might change after the element rendered. - const protocol = isEmail && 'mailto:' || editor.config.get( 'link.defaultProtocol' ) || defaultProtocol; - const parsedValue = !hasProtocol && value ? protocol + value : value; + const protocol = isEmail && 'mailto:' || defaultProtocol; + const parsedValue = value && isProtocolNeeded ? protocol + value : value; editor.execute( 'link', parsedValue, formView.getDecoratorSwitchesState() ); this._closeFormView(); diff --git a/packages/ckeditor5-link/src/ui/linkformview.js b/packages/ckeditor5-link/src/ui/linkformview.js index 12fb97d865a..e20a747e8d0 100644 --- a/packages/ckeditor5-link/src/ui/linkformview.js +++ b/packages/ckeditor5-link/src/ui/linkformview.js @@ -21,8 +21,6 @@ import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker'; import FocusCycler from '@ckeditor/ckeditor5-ui/src/focuscycler'; import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler'; -import { DEFAULT_PROTOCOL } from '../utils'; - import checkIcon from '@ckeditor/ckeditor5-core/theme/icons/check.svg'; import cancelIcon from '@ckeditor/ckeditor5-core/theme/icons/cancel.svg'; import '../../theme/linkform.css'; @@ -210,10 +208,10 @@ export default class LinkFormView extends View { * Creates a labeled input view. * * @private - * @param {module:link/utils~DefaultProtocol} [protocol=http://] A value of a protocol to be displayed in the input's placeholder. + * @param {String} [protocol=http://] A value of a protocol to be displayed in the input's placeholder. * @returns {module:ui/labeledfield/labeledfieldview~LabeledFieldView} Labeled field view instance. */ - _createUrlInput( protocol = DEFAULT_PROTOCOL ) { + _createUrlInput( protocol = 'https://' ) { const t = this.locale.t; const labeledInput = new LabeledFieldView( this.locale, createLabeledInputText ); diff --git a/packages/ckeditor5-link/src/utils.js b/packages/ckeditor5-link/src/utils.js index 4eafb2be35a..4c80d39e9c0 100644 --- a/packages/ckeditor5-link/src/utils.js +++ b/packages/ckeditor5-link/src/utils.js @@ -12,13 +12,6 @@ import { upperFirst } from 'lodash-es'; const ATTRIBUTE_WHITESPACES = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g; // eslint-disable-line no-control-regex const SAFE_URL = /^(?:(?:https?|ftps?|mailto):|[^a-z]|[a-z+.-]+(?:[^a-z+.:-]|$))/i; -/** - * A default link protocol value. - * @typedef {String} module:link/utils~DefaultProtocol - * @default 'http://' - */ -export const DEFAULT_PROTOCOL = 'http://'; - /** * Returns `true` if a given view node is the link element. * diff --git a/packages/ckeditor5-link/tests/linkui.js b/packages/ckeditor5-link/tests/linkui.js index 602320bcafc..ae7c422e57a 100644 --- a/packages/ckeditor5-link/tests/linkui.js +++ b/packages/ckeditor5-link/tests/linkui.js @@ -21,8 +21,6 @@ import ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextu import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview'; import View from '@ckeditor/ckeditor5-ui/src/view'; -import { DEFAULT_PROTOCOL } from '../src/utils'; - import ClickObserver from '@ckeditor/ckeditor5-engine/src/view/observer/clickobserver'; describe( 'LinkUI', () => { @@ -932,14 +930,61 @@ describe( 'LinkUI', () => { } ); } ); - it( 'should use `http://` as a default link protocol without any configuration', () => { + it( 'should not add a protocol without the configuration', () => { + formView.urlInputView.fieldView.value = 'ckeditor.com'; + formView.fire( 'submit' ); + + expect( formView.urlInputView.fieldView.value ).to.equal( 'ckeditor.com' ); + } ); + + it( 'should not add a protocol to the local links even when `config.link.defaultProtocol` configured', () => { + editor.config.set( 'link.defaultProtocol', 'http://' ); + + formView.urlInputView.fieldView.value = '#test'; + formView.fire( 'submit' ); + + expect( formView.urlInputView.fieldView.value ).to.equal( '#test' ); + } ); + + it( 'should not add a protocol to the relative links even when `config.link.defaultProtocol` configured', () => { + editor.config.set( 'link.defaultProtocol', 'http://' ); + + formView.urlInputView.fieldView.value = '/test.html'; + formView.fire( 'submit' ); + + expect( formView.urlInputView.fieldView.value ).to.equal( '/test.html' ); + } ); + + it( 'should not add a protocol when given provided wihitn the value even when `config.link.defaultProtocol` configured', () => { + editor.config.set( 'link.defaultProtocol', 'http://' ); + + formView.urlInputView.fieldView.value = 'http://example.com'; + formView.fire( 'submit' ); + + expect( formView.urlInputView.fieldView.value ).to.equal( 'http://example.com' ); + } ); + + it( 'should use the "http://" protocol when it\'s configured', () => { + editor.config.set( 'link.defaultProtocol', 'http://' ); + formView.urlInputView.fieldView.value = 'ckeditor.com'; formView.fire( 'submit' ); expect( formView.urlInputView.fieldView.value ).to.equal( 'http://ckeditor.com' ); } ); + it( 'should use the "http://" protocol when it\'s configured and form input value contains "www."', () => { + editor.config.set( 'link.defaultProtocol', 'http://' ); + + formView.urlInputView.fieldView.value = 'www.ckeditor.com'; + formView.fire( 'submit' ); + + expect( formView.urlInputView.fieldView.value ).to.equal( 'http://www.ckeditor.com' ); + } ); + it( 'should propagate the protocol to the link\'s `linkHref` attribute in model', () => { + editor.config.set( 'link.defaultProtocol', 'http://' ); + setModelData( editor.model, '[ckeditor.com]' ); formView.urlInputView.fieldView.value = 'ckeditor.com'; @@ -951,6 +996,8 @@ describe( 'LinkUI', () => { } ); it( 'should detect an email on submitting the form and add "mailto:" protocol automatically to the provided value', () => { + editor.config.set( 'link.defaultProtocol', 'http://' ); + setModelData( editor.model, '[email@example.com]' ); formView.urlInputView.fieldView.value = 'email@example.com'; @@ -961,6 +1008,16 @@ describe( 'LinkUI', () => { '[<$text linkHref="mailto:email@example.com">email@example.com]' ); } ); + + it( 'should not add an email protocol when given provided wihitn the value' + + 'even when `config.link.defaultProtocol` configured', () => { + editor.config.set( 'link.defaultProtocol', 'mailto:' ); + + formView.urlInputView.fieldView.value = 'mailto:test@example.com'; + formView.fire( 'submit' ); + + expect( formView.urlInputView.fieldView.value ).to.equal( 'mailto:test@example.com' ); + } ); } ); describe( 'binding', () => { @@ -1120,7 +1177,7 @@ describe( 'LinkUI', () => { formView.fire( 'submit' ); expect( executeSpy.calledOnce ).to.be.true; - expect( executeSpy.calledWithExactly( 'link', DEFAULT_PROTOCOL + 'url', { linkIsFoo: true } ) ).to.be.true; + expect( executeSpy.calledWithExactly( 'link', 'url', { linkIsFoo: true } ) ).to.be.true; } ); it( 'should reset switch state when form view is closed', () => { diff --git a/packages/ckeditor5-link/tests/ui/linkformview.js b/packages/ckeditor5-link/tests/ui/linkformview.js index b4c511dec43..402274d89c7 100644 --- a/packages/ckeditor5-link/tests/ui/linkformview.js +++ b/packages/ckeditor5-link/tests/ui/linkformview.js @@ -21,8 +21,6 @@ import Link from '../../src/link'; import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin'; import mix from '@ckeditor/ckeditor5-utils/src/mix'; -import { DEFAULT_PROTOCOL } from '../../src/utils'; - describe( 'LinkFormView', () => { let view; @@ -85,7 +83,7 @@ describe( 'LinkFormView', () => { describe( 'url input view', () => { it( 'has placeholder', () => { - expect( view.urlInputView.fieldView.placeholder ).to.equal( DEFAULT_PROTOCOL + 'example.com' ); + expect( view.urlInputView.fieldView.placeholder ).to.equal( 'https://example.com' ); } ); } ); From 1c60eae3fd64ea71fb832e45f9be5a71a294bcbf Mon Sep 17 00:00:00 2001 From: panr Date: Thu, 4 Jun 2020 14:44:40 +0200 Subject: [PATCH 09/15] Fix dev comment. --- packages/ckeditor5-link/src/linkui.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ckeditor5-link/src/linkui.js b/packages/ckeditor5-link/src/linkui.js index d74bc131bf1..f4bb1e4de95 100644 --- a/packages/ckeditor5-link/src/linkui.js +++ b/packages/ckeditor5-link/src/linkui.js @@ -157,13 +157,13 @@ export default class LinkUI extends Plugin { this.listenTo( formView, 'submit', () => { const { value } = formView.urlInputView.fieldView.element; + // It's good to check the config for the second time on submit. + // This will cover more dynamic cases, when protocol might change after the element has been rendered. const defaultProtocol = editor.config.get( 'link.defaultProtocol' ); const isProtocolNeeded = !!defaultProtocol && !( /^((\w+:(\/{2,})?)|(\W))/gmi ).test( value ); const isEmail = ( /[\w-]+@[\w-]+\.+[\w-]+/gmi ).test( value ); - // It's good to check config second time on submit for more dynamic cases - // when protocol might change after the element rendered. const protocol = isEmail && 'mailto:' || defaultProtocol; const parsedValue = value && isProtocolNeeded ? protocol + value : value; From 6c03572a0ddfa4ba1eab327a64c80d0984403dd0 Mon Sep 17 00:00:00 2001 From: panr Date: Thu, 4 Jun 2020 14:52:25 +0200 Subject: [PATCH 10/15] Add dev comment for the regex part. --- packages/ckeditor5-link/src/linkui.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/ckeditor5-link/src/linkui.js b/packages/ckeditor5-link/src/linkui.js index f4bb1e4de95..3a44a96ee77 100644 --- a/packages/ckeditor5-link/src/linkui.js +++ b/packages/ckeditor5-link/src/linkui.js @@ -161,6 +161,7 @@ export default class LinkUI extends Plugin { // This will cover more dynamic cases, when protocol might change after the element has been rendered. const defaultProtocol = editor.config.get( 'link.defaultProtocol' ); + // The regex checks for the protocol syntax ('xxxx://') or non-word charecters at the begining of the link ('/', '#' etc.). const isProtocolNeeded = !!defaultProtocol && !( /^((\w+:(\/{2,})?)|(\W))/gmi ).test( value ); const isEmail = ( /[\w-]+@[\w-]+\.+[\w-]+/gmi ).test( value ); From 60d498feb6cb7cbac715e7a17469ab27e96012fe Mon Sep 17 00:00:00 2001 From: panr Date: Thu, 4 Jun 2020 14:53:53 +0200 Subject: [PATCH 11/15] Fix dev comment. --- packages/ckeditor5-link/src/linkui.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/ckeditor5-link/src/linkui.js b/packages/ckeditor5-link/src/linkui.js index 3a44a96ee77..96d692aa573 100644 --- a/packages/ckeditor5-link/src/linkui.js +++ b/packages/ckeditor5-link/src/linkui.js @@ -161,7 +161,8 @@ export default class LinkUI extends Plugin { // This will cover more dynamic cases, when protocol might change after the element has been rendered. const defaultProtocol = editor.config.get( 'link.defaultProtocol' ); - // The regex checks for the protocol syntax ('xxxx://') or non-word charecters at the begining of the link ('/', '#' etc.). + // The regex checks for the protocol syntax ('xxxx://' or 'xxxx:') + // or non-word charecters at the begining of the link ('/', '#' etc.). const isProtocolNeeded = !!defaultProtocol && !( /^((\w+:(\/{2,})?)|(\W))/gmi ).test( value ); const isEmail = ( /[\w-]+@[\w-]+\.+[\w-]+/gmi ).test( value ); From a653407cca29e21940c45b8c7e9a2bb3703a5577 Mon Sep 17 00:00:00 2001 From: panr Date: Thu, 4 Jun 2020 15:35:12 +0200 Subject: [PATCH 12/15] Add @ckeditor/ckeditor5-basic-styles --- packages/ckeditor5-link/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/ckeditor5-link/package.json b/packages/ckeditor5-link/package.json index 1c1b25dc39a..f250e83759e 100644 --- a/packages/ckeditor5-link/package.json +++ b/packages/ckeditor5-link/package.json @@ -16,6 +16,7 @@ "lodash-es": "^4.17.15" }, "devDependencies": { + "@ckeditor/ckeditor5-basic-styles": "^19.0.1", "@ckeditor/ckeditor5-block-quote": "^19.0.1", "@ckeditor/ckeditor5-clipboard": "^19.0.1", "@ckeditor/ckeditor5-editor-classic": "^19.0.1", From de6f4d9d3c2f80ec3abd3fb7774c19c5f345deff Mon Sep 17 00:00:00 2001 From: panr Date: Wed, 10 Jun 2020 14:25:01 +0200 Subject: [PATCH 13/15] Fix code and tests. --- packages/ckeditor5-link/src/linkui.js | 12 +-- packages/ckeditor5-link/tests/linkui.js | 123 +++++++++++++++--------- 2 files changed, 81 insertions(+), 54 deletions(-) diff --git a/packages/ckeditor5-link/src/linkui.js b/packages/ckeditor5-link/src/linkui.js index 96d692aa573..1e78a65f05e 100644 --- a/packages/ckeditor5-link/src/linkui.js +++ b/packages/ckeditor5-link/src/linkui.js @@ -21,6 +21,8 @@ import LinkActionsView from './ui/linkactionsview'; import linkIcon from '../theme/icons/link.svg'; const linkKeystroke = 'Ctrl+K'; +const protocolRegExp = /^((\w+:(\/{2,})?)|(\W))/i; +const emailRegExp = /[\w-]+@[\w-]+\.+[\w-]+/i; /** * The link UI plugin. It introduces the `'link'` and `'unlink'` buttons and support for the Ctrl+K keystroke. @@ -157,16 +159,12 @@ export default class LinkUI extends Plugin { this.listenTo( formView, 'submit', () => { const { value } = formView.urlInputView.fieldView.element; - // It's good to check the config for the second time on submit. - // This will cover more dynamic cases, when protocol might change after the element has been rendered. - const defaultProtocol = editor.config.get( 'link.defaultProtocol' ); - // The regex checks for the protocol syntax ('xxxx://' or 'xxxx:') // or non-word charecters at the begining of the link ('/', '#' etc.). - const isProtocolNeeded = !!defaultProtocol && !( /^((\w+:(\/{2,})?)|(\W))/gmi ).test( value ); - const isEmail = ( /[\w-]+@[\w-]+\.+[\w-]+/gmi ).test( value ); + const isProtocolNeeded = !!defaultProtocol && !protocolRegExp.test( value ); + const isEmail = emailRegExp.test( value ); - const protocol = isEmail && 'mailto:' || defaultProtocol; + const protocol = isEmail ? 'mailto:' : defaultProtocol; const parsedValue = value && isProtocolNeeded ? protocol + value : value; editor.execute( 'link', parsedValue, formView.getDecoratorSwitchesState() ); diff --git a/packages/ckeditor5-link/tests/linkui.js b/packages/ckeditor5-link/tests/linkui.js index ae7c422e57a..9d4b57afe4b 100644 --- a/packages/ckeditor5-link/tests/linkui.js +++ b/packages/ckeditor5-link/tests/linkui.js @@ -891,6 +891,27 @@ describe( 'LinkUI', () => { describe( 'link form view', () => { let focusEditableSpy; + const createEditorWithDefaultProtocol = defaultProtocol => { + return ClassicTestEditor + .create( editorElement, { + plugins: [ LinkEditing, LinkUI, Paragraph, BlockQuote ], + link: { defaultProtocol } + } ) + .then( editor => { + const linkUIFeature = editor.plugins.get( LinkUI ); + const formView = linkUIFeature.formView; + + formView.render(); + + editor.model.schema.extend( '$text', { + allowIn: '$root', + allowAttributes: 'linkHref' + } ); + + return { editor, formView }; + } ); + }; + beforeEach( () => { focusEditableSpy = testUtils.sinon.spy( editor.editing.view, 'focus' ); } ); @@ -906,13 +927,6 @@ describe( 'LinkUI', () => { } ); describe( 'link protocol', () => { - beforeEach( () => { - editor.model.schema.extend( '$text', { - allowIn: '$root', - allowAttributes: 'linkHref' - } ); - } ); - it( 'should use a default link protocol from the `config.link.defaultProtocol` when provided', () => { return ClassicTestEditor .create( editorElement, { @@ -925,7 +939,6 @@ describe( 'LinkUI', () => { expect( defaultProtocol ).to.equal( 'https://' ); - editorElement.remove(); editor.destroy(); } ); } ); @@ -938,85 +951,101 @@ describe( 'LinkUI', () => { } ); it( 'should not add a protocol to the local links even when `config.link.defaultProtocol` configured', () => { - editor.config.set( 'link.defaultProtocol', 'http://' ); + return createEditorWithDefaultProtocol( 'http://' ).then( ( { editor, formView } ) => { + formView.urlInputView.fieldView.value = '#test'; + formView.fire( 'submit' ); - formView.urlInputView.fieldView.value = '#test'; - formView.fire( 'submit' ); + expect( formView.urlInputView.fieldView.value ).to.equal( '#test' ); - expect( formView.urlInputView.fieldView.value ).to.equal( '#test' ); + editor.destroy(); + } ); } ); it( 'should not add a protocol to the relative links even when `config.link.defaultProtocol` configured', () => { - editor.config.set( 'link.defaultProtocol', 'http://' ); + return createEditorWithDefaultProtocol( 'http://' ).then( ( { editor, formView } ) => { + formView.urlInputView.fieldView.value = '/test.html'; + formView.fire( 'submit' ); - formView.urlInputView.fieldView.value = '/test.html'; - formView.fire( 'submit' ); + expect( formView.urlInputView.fieldView.value ).to.equal( '/test.html' ); - expect( formView.urlInputView.fieldView.value ).to.equal( '/test.html' ); + editor.destroy(); + } ); } ); it( 'should not add a protocol when given provided wihitn the value even when `config.link.defaultProtocol` configured', () => { - editor.config.set( 'link.defaultProtocol', 'http://' ); + return createEditorWithDefaultProtocol( 'http://' ).then( ( { editor, formView } ) => { + formView.urlInputView.fieldView.value = 'http://example.com'; + formView.fire( 'submit' ); - formView.urlInputView.fieldView.value = 'http://example.com'; - formView.fire( 'submit' ); + expect( formView.urlInputView.fieldView.value ).to.equal( 'http://example.com' ); - expect( formView.urlInputView.fieldView.value ).to.equal( 'http://example.com' ); + editor.destroy(); + } ); } ); it( 'should use the "http://" protocol when it\'s configured', () => { - editor.config.set( 'link.defaultProtocol', 'http://' ); + return createEditorWithDefaultProtocol( 'http://' ).then( ( { editor, formView } ) => { + formView.urlInputView.fieldView.value = 'ckeditor.com'; + formView.fire( 'submit' ); - formView.urlInputView.fieldView.value = 'ckeditor.com'; - formView.fire( 'submit' ); + expect( formView.urlInputView.fieldView.value ).to.equal( 'http://ckeditor.com' ); - expect( formView.urlInputView.fieldView.value ).to.equal( 'http://ckeditor.com' ); + editor.destroy(); + } ); } ); it( 'should use the "http://" protocol when it\'s configured and form input value contains "www."', () => { - editor.config.set( 'link.defaultProtocol', 'http://' ); + return createEditorWithDefaultProtocol( 'http://' ).then( ( { editor, formView } ) => { + formView.urlInputView.fieldView.value = 'www.ckeditor.com'; + formView.fire( 'submit' ); - formView.urlInputView.fieldView.value = 'www.ckeditor.com'; - formView.fire( 'submit' ); + expect( formView.urlInputView.fieldView.value ).to.equal( 'http://www.ckeditor.com' ); - expect( formView.urlInputView.fieldView.value ).to.equal( 'http://www.ckeditor.com' ); + editor.destroy(); + } ); } ); it( 'should propagate the protocol to the link\'s `linkHref` attribute in model', () => { - editor.config.set( 'link.defaultProtocol', 'http://' ); + return createEditorWithDefaultProtocol( 'http://' ).then( ( { editor, formView } ) => { + setModelData( editor.model, '[ckeditor.com]' ); - setModelData( editor.model, '[ckeditor.com]' ); + formView.urlInputView.fieldView.value = 'ckeditor.com'; + formView.fire( 'submit' ); - formView.urlInputView.fieldView.value = 'ckeditor.com'; - formView.fire( 'submit' ); + expect( getModelData( editor.model ) ).to.equal( + '[<$text linkHref="http://ckeditor.com">ckeditor.com]' + ); - expect( getModelData( editor.model ) ).to.equal( - '[<$text linkHref="http://ckeditor.com">ckeditor.com]' - ); + editor.destroy(); + } ); } ); it( 'should detect an email on submitting the form and add "mailto:" protocol automatically to the provided value', () => { - editor.config.set( 'link.defaultProtocol', 'http://' ); + return createEditorWithDefaultProtocol( 'http://' ).then( ( { editor, formView } ) => { + setModelData( editor.model, '[email@example.com]' ); - setModelData( editor.model, '[email@example.com]' ); + formView.urlInputView.fieldView.value = 'email@example.com'; + formView.fire( 'submit' ); - formView.urlInputView.fieldView.value = 'email@example.com'; - formView.fire( 'submit' ); + expect( formView.urlInputView.fieldView.value ).to.equal( 'mailto:email@example.com' ); + expect( getModelData( editor.model ) ).to.equal( + '[<$text linkHref="mailto:email@example.com">email@example.com]' + ); - expect( formView.urlInputView.fieldView.value ).to.equal( 'mailto:email@example.com' ); - expect( getModelData( editor.model ) ).to.equal( - '[<$text linkHref="mailto:email@example.com">email@example.com]' - ); + editor.destroy(); + } ); } ); it( 'should not add an email protocol when given provided wihitn the value' + 'even when `config.link.defaultProtocol` configured', () => { - editor.config.set( 'link.defaultProtocol', 'mailto:' ); + return createEditorWithDefaultProtocol( 'mailto:' ).then( ( { editor, formView } ) => { + formView.urlInputView.fieldView.value = 'mailto:test@example.com'; + formView.fire( 'submit' ); - formView.urlInputView.fieldView.value = 'mailto:test@example.com'; - formView.fire( 'submit' ); + expect( formView.urlInputView.fieldView.value ).to.equal( 'mailto:test@example.com' ); - expect( formView.urlInputView.fieldView.value ).to.equal( 'mailto:test@example.com' ); + editor.destroy(); + } ); } ); } ); From e9b938eabbf4327cd8e9f49f91f5ea02a0229138 Mon Sep 17 00:00:00 2001 From: panr Date: Wed, 10 Jun 2020 14:53:49 +0200 Subject: [PATCH 14/15] Change manual test. --- .../ckeditor5-link/tests/manual/protocol.html | 25 +++++---- .../ckeditor5-link/tests/manual/protocol.js | 54 ++++++++----------- .../ckeditor5-link/tests/manual/protocol.md | 4 +- 3 files changed, 38 insertions(+), 45 deletions(-) diff --git a/packages/ckeditor5-link/tests/manual/protocol.html b/packages/ckeditor5-link/tests/manual/protocol.html index 8ed4a7d7a4e..1a2d083bcb5 100644 --- a/packages/ckeditor5-link/tests/manual/protocol.html +++ b/packages/ckeditor5-link/tests/manual/protocol.html @@ -35,18 +35,25 @@ } -

The default configuration for the link protocol has been set to .

-

...but you can dynamically change it:

-
- - - - -
+

Feature is disabled

+
+

This is CKEditor5 from CKSource. If you need more information please contact us at support@example.com.

+
-
+

http://

+

This is CKEditor5 from CKSource. If you need more information please contact us at support@example.com [1].

[1]When feature enabled: copy the email address and create a link with it (mailto: protocol will be added automatically).

+ +

https://

+
+

This is CKEditor5 from CKSource. If you need more information please contact us at support@example.com.

+
+ +

mailto:

+
+

This is CKEditor5 from CKSource. If you need more information please contact us at support@example.com.

+
diff --git a/packages/ckeditor5-link/tests/manual/protocol.js b/packages/ckeditor5-link/tests/manual/protocol.js index d2d75b0724a..9f33f4b3409 100644 --- a/packages/ckeditor5-link/tests/manual/protocol.js +++ b/packages/ckeditor5-link/tests/manual/protocol.js @@ -13,37 +13,25 @@ import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph'; import Undo from '@ckeditor/ckeditor5-undo/src/undo'; import Superscript from '@ckeditor/ckeditor5-basic-styles/src/superscript'; -ClassicEditor - .create( document.querySelector( '#editor' ), { - plugins: [ Link, Typing, Paragraph, Undo, Enter, Superscript ], - toolbar: [ 'link', 'undo', 'redo' ], - link: { - addTargetToExternalLinks: true, - defaultProtocol: 'http://' - } - } ) - .then( editor => { - window.editor = editor; - - const LinkUIPlugin = editor.plugins.get( 'LinkUI' ); - const formView = LinkUIPlugin.formView; - const defaultProtocol = editor.config.get( 'link.defaultProtocol' ); - - document.getElementById( 'default-protocol' ).innerText = defaultProtocol; - - document.querySelectorAll( '#protocol-settings input[type="radio"]' ).forEach( radio => { - radio.checked = radio.value === defaultProtocol; - - radio.addEventListener( 'click', ( { - target: { value: protocol } - } ) => { - editor.config.set( 'link.defaultProtocol', protocol === 'none' ? undefined : protocol ); - - // Change input placeholder just for manual test's case to provide more dynamic behavior. - formView.urlInputView.fieldView.placeholder = protocol === 'none' ? 'https://example.com' : protocol + 'example.com'; - } ); +createEditorWithDefaultProtocol( '#editor0' ); +createEditorWithDefaultProtocol( '#editor1', 'http://' ); +createEditorWithDefaultProtocol( '#editor2', 'https://' ); +createEditorWithDefaultProtocol( '#editor3', 'mailto:' ); + +function createEditorWithDefaultProtocol( editor, defaultProtocol ) { + return ClassicEditor + .create( document.querySelector( editor ), { + plugins: [ Link, Typing, Paragraph, Undo, Enter, Superscript ], + toolbar: [ 'link', 'undo', 'redo' ], + link: { + addTargetToExternalLinks: true, + ...defaultProtocol && { defaultProtocol } + } + } ) + .then( editor => { + window.editor = editor; + } ) + .catch( err => { + console.error( err.stack ); } ); - } ) - .catch( err => { - console.error( err.stack ); - } ); +} diff --git a/packages/ckeditor5-link/tests/manual/protocol.md b/packages/ckeditor5-link/tests/manual/protocol.md index 2a5266c561a..5c4f80f84fe 100644 --- a/packages/ckeditor5-link/tests/manual/protocol.md +++ b/packages/ckeditor5-link/tests/manual/protocol.md @@ -2,7 +2,5 @@ This test checks whether: - `config.link.defaultProtocol` applies. -- user is able to dynamically change the link protocol (just as an extended example of usage). +- when input value starts with a protocol-like syntax (like `http://` etc.) or any non-word (like `#` or `/`) then `defaultProtocol` won't be applied. - the plugin dynamically change link protocol to `mailto:` when email address was detected. - -When you dynamically change the value of the link protocol, the form input placeholder should change as well. From e5bf396a5a51b03853ca13982a01a8cd84122cbb Mon Sep 17 00:00:00 2001 From: panr Date: Wed, 10 Jun 2020 14:56:57 +0200 Subject: [PATCH 15/15] Fix typos. --- packages/ckeditor5-link/tests/linkui.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ckeditor5-link/tests/linkui.js b/packages/ckeditor5-link/tests/linkui.js index 9d4b57afe4b..1f09e43f672 100644 --- a/packages/ckeditor5-link/tests/linkui.js +++ b/packages/ckeditor5-link/tests/linkui.js @@ -972,7 +972,7 @@ describe( 'LinkUI', () => { } ); } ); - it( 'should not add a protocol when given provided wihitn the value even when `config.link.defaultProtocol` configured', () => { + it( 'should not add a protocol when given provided within the value even when `config.link.defaultProtocol` configured', () => { return createEditorWithDefaultProtocol( 'http://' ).then( ( { editor, formView } ) => { formView.urlInputView.fieldView.value = 'http://example.com'; formView.fire( 'submit' ); @@ -1036,7 +1036,7 @@ describe( 'LinkUI', () => { } ); } ); - it( 'should not add an email protocol when given provided wihitn the value' + + it( 'should not add an email protocol when given provided within the value' + 'even when `config.link.defaultProtocol` configured', () => { return createEditorWithDefaultProtocol( 'mailto:' ).then( ( { editor, formView } ) => { formView.urlInputView.fieldView.value = 'mailto:test@example.com';