-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7370 from ckeditor/i/4858
Feature (link): Introduced the `config.link.defaultProtocol` option for automatically adding it to the links when it's not provided by the user in the link form. Closes #4858.
- Loading branch information
Showing
9 changed files
with
315 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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( ... ); | ||
``` | ||
|
||
<info-box> | ||
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 `[email protected]`, the plugin will change it automatically to `mailto:[email protected]`. | ||
</info-box> | ||
|
||
#### 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. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,6 +57,28 @@ 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. | ||
* 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 `[email protected]` | ||
* the plugin will automatically change it to `mailto:[email protected]`. | ||
* | ||
* ClassicEditor | ||
* .create( editorElement, { | ||
* link: { | ||
* defaultProtocol: 'http://' | ||
* } | ||
* } ) | ||
* .then( ... ) | ||
* .catch( ... ); | ||
* | ||
* **NOTE:** In case no configuration is provided, the editor won't auto-fix the links. | ||
* | ||
* @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 `//`. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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'; | ||
|
@@ -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' ); | ||
} ); | ||
|
@@ -905,6 +926,129 @@ describe( 'LinkUI', () => { | |
expect( editor.ui.focusTracker.isFocused ).to.be.true; | ||
} ); | ||
|
||
describe( 'link protocol', () => { | ||
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://' ); | ||
|
||
editor.destroy(); | ||
} ); | ||
} ); | ||
|
||
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', () => { | ||
return createEditorWithDefaultProtocol( 'http://' ).then( ( { editor, formView } ) => { | ||
formView.urlInputView.fieldView.value = '#test'; | ||
formView.fire( 'submit' ); | ||
|
||
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', () => { | ||
return createEditorWithDefaultProtocol( 'http://' ).then( ( { editor, formView } ) => { | ||
formView.urlInputView.fieldView.value = '/test.html'; | ||
formView.fire( 'submit' ); | ||
|
||
expect( formView.urlInputView.fieldView.value ).to.equal( '/test.html' ); | ||
|
||
editor.destroy(); | ||
} ); | ||
} ); | ||
|
||
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' ); | ||
|
||
expect( formView.urlInputView.fieldView.value ).to.equal( 'http://example.com' ); | ||
|
||
editor.destroy(); | ||
} ); | ||
} ); | ||
|
||
it( 'should use the "http://" protocol when it\'s configured', () => { | ||
return createEditorWithDefaultProtocol( 'http://' ).then( ( { editor, formView } ) => { | ||
formView.urlInputView.fieldView.value = 'ckeditor.com'; | ||
formView.fire( 'submit' ); | ||
|
||
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."', () => { | ||
return createEditorWithDefaultProtocol( 'http://' ).then( ( { editor, formView } ) => { | ||
formView.urlInputView.fieldView.value = 'www.ckeditor.com'; | ||
formView.fire( 'submit' ); | ||
|
||
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', () => { | ||
return createEditorWithDefaultProtocol( 'http://' ).then( ( { editor, formView } ) => { | ||
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</$text>]' | ||
); | ||
|
||
editor.destroy(); | ||
} ); | ||
} ); | ||
|
||
it( 'should detect an email on submitting the form and add "mailto:" protocol automatically to the provided value', () => { | ||
return createEditorWithDefaultProtocol( 'http://' ).then( ( { editor, formView } ) => { | ||
setModelData( editor.model, '[[email protected]]' ); | ||
|
||
formView.urlInputView.fieldView.value = '[email protected]'; | ||
formView.fire( 'submit' ); | ||
|
||
expect( formView.urlInputView.fieldView.value ).to.equal( 'mailto:[email protected]' ); | ||
expect( getModelData( editor.model ) ).to.equal( | ||
'[<$text linkHref="mailto:[email protected]">[email protected]</$text>]' | ||
); | ||
|
||
editor.destroy(); | ||
} ); | ||
} ); | ||
|
||
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:[email protected]'; | ||
formView.fire( 'submit' ); | ||
|
||
expect( formView.urlInputView.fieldView.value ).to.equal( 'mailto:[email protected]' ); | ||
|
||
editor.destroy(); | ||
} ); | ||
} ); | ||
} ); | ||
|
||
describe( 'binding', () => { | ||
beforeEach( () => { | ||
setModelData( editor.model, '<paragraph>f[o]o</paragraph>' ); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<style> | ||
code { | ||
background: hsl(0, 0%, 90%); | ||
} | ||
|
||
sup { | ||
position: relative; | ||
} | ||
|
||
.ck-editor__editable sup:after { | ||
content: ''; | ||
display: inline-block; | ||
position: absolute; | ||
width: 14px; | ||
height: 14px; | ||
left: 1px; | ||
top: 1px; | ||
background: hsla(207, 87%, 55%, 0.5); | ||
border-radius: 50px; | ||
animation: pulse 2s linear infinite; | ||
} | ||
|
||
@keyframes pulse { | ||
0% { | ||
transform: scale(1); | ||
} | ||
|
||
50% { | ||
transform: scale(2); | ||
} | ||
|
||
100% { | ||
transform: scale(1); | ||
} | ||
} | ||
</style> | ||
|
||
|
||
<h2><code>Feature is disabled</code></h2> | ||
<div id="editor0"> | ||
<p>This is <a href="http://ckeditor.com">CKEditor5</a> from <a href="http://cksource.com">CKSource</a>. If you need more information please contact us at [email protected].</p> | ||
</div> | ||
|
||
<h2><code>http://</code></h2> | ||
<div id="editor1"> | ||
<p>This is <a href="http://ckeditor.com">CKEditor5</a> from <a href="http://cksource.com">CKSource</a>. If you need more information please contact us at [email protected] <sup class="indicator">[1]</sup>.</p> | ||
</div> | ||
|
||
<p><sup>[1]</sup><strong>When feature enabled:</strong> copy the email address and create a link with it (<code>mailto:</code> protocol will be added automatically).</p> | ||
|
||
<h2><code>https://</code></h2> | ||
<div id="editor2"> | ||
<p>This is <a href="http://ckeditor.com">CKEditor5</a> from <a href="http://cksource.com">CKSource</a>. If you need more information please contact us at [email protected].</p> | ||
</div> | ||
|
||
<h2><code>mailto:</code></h2> | ||
<div id="editor3"> | ||
<p>This is <a href="http://ckeditor.com">CKEditor5</a> from <a href="http://cksource.com">CKSource</a>. If you need more information please contact us at [email protected].</p> | ||
</div> |
Oops, something went wrong.