Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge pull request #235 from ckeditor/t/233
Browse files Browse the repository at this point in the history
Fix: Provide missing upcast converter for link decorators. Closes #233.
  • Loading branch information
jodator committed Jun 28, 2019
2 parents 40d8266 + df03bf5 commit 4161eb1
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 28 deletions.
20 changes: 13 additions & 7 deletions src/linkediting.js
Expand Up @@ -156,17 +156,23 @@ export default class LinkEditing extends Plugin {
model: decorator.id,
view: ( manualDecoratorName, writer ) => {
if ( manualDecoratorName ) {
const element = writer.createAttributeElement(
'a',
manualDecorators.get( decorator.id ).attributes,
{
priority: 5
}
);
const attributes = manualDecorators.get( decorator.id ).attributes;
const element = writer.createAttributeElement( 'a', attributes, { priority: 5 } );
writer.setCustomProperty( 'link', true, element );

return element;
}
} } );

editor.conversion.for( 'upcast' ).elementToAttribute( {
view: {
name: 'a',
attributes: manualDecorators.get( decorator.id ).attributes
},
model: {
key: decorator.id
}
} );
} );
}

Expand Down
84 changes: 84 additions & 0 deletions tests/linkediting.js
Expand Up @@ -587,5 +587,89 @@ describe( 'LinkEditing', () => {
expect( editor.getData() ).to.equal( '<p><a href="http://example.com">foo</a>bar</p>' );
} );
} );

describe( 'upcast converter', () => {
it( 'should upcast attributes from initial data', done => {
VirtualTestEditor
.create( {
initialData: '<p><a href="url" target="_blank" rel="noopener noreferrer" download="file">Foo</a>' +
'<a href="example.com" download="file">Bar</a></p>',
plugins: [ Paragraph, LinkEditing, Enter ],
link: {
decorators: {
isExternal: {
mode: 'manual',
label: 'Open in a new window',
attributes: {
target: '_blank',
rel: 'noopener noreferrer'
}
},
isDownloadable: {
mode: 'manual',
label: 'Downloadable',
attributes: {
download: 'file'
}
}
}
}
} )
.then( newEditor => {
editor = newEditor;
model = editor.model;

expect( getModelData( model, { withoutSelection: true } ) ).to.equal(
'<paragraph>' +
'<$text linkHref="url" linkIsDownloadable="true" linkIsExternal="true">Foo</$text>' +
'<$text linkHref="example.com" linkIsDownloadable="true">Bar</$text>' +
'</paragraph>'
);
} )
.then( done )
.catch( done );
} );

it( 'should not upcast partial and incorrect attributes', done => {
VirtualTestEditor
.create( {
initialData: '<p><a href="url" target="_blank" download="something">Foo</a>' +
'<a href="example.com" download="test">Bar</a></p>',
plugins: [ Paragraph, LinkEditing, Enter ],
link: {
decorators: {
isExternal: {
mode: 'manual',
label: 'Open in a new window',
attributes: {
target: '_blank',
rel: 'noopener noreferrer'
}
},
isDownloadable: {
mode: 'manual',
label: 'Downloadable',
attributes: {
download: 'file'
}
}
}
}
} )
.then( newEditor => {
editor = newEditor;
model = editor.model;

expect( getModelData( model, { withoutSelection: true } ) ).to.equal(
'<paragraph>' +
'<$text linkHref="url">Foo</$text>' +
'<$text linkHref="example.com">Bar</$text>' +
'</paragraph>'
);
} )
.then( done )
.catch( done );
} );
} );
} );
} );
10 changes: 5 additions & 5 deletions tests/manual/linkdecorator.html
@@ -1,16 +1,16 @@
<h2>Manual decorators</h2>
<div id="editor">
<p>This is <a href="http://ckeditor.com">CKEditor5</a> from <a href="http://cksource.com">CKSource</a>.</p>
<p>This is <a href="//ckeditor.com">CKEditor5</a> as schemaless url.</p>
<p>This is <a href="http://ckeditor.com" target="_blank" rel="noopener noreferrer">CKEditor5</a> from <a href="http://cksource.com" download="download" target="_blank" rel="noopener noreferrer" >CKSource</a>.</p>
<p>This is <a href="//ckeditor.com" class="gallery">CKEditor5</a> as schemaless url.</p>
<p>This is <a href="#anchor">anchor</a> on this page.</p>
<p>This is some random <a href="ftp://127.0.0.1">ftp address</a>.</p>
<p>This is some random <a href="ftp://127.0.0.1" download="download">ftp address</a>.</p>
<p>This is some <a href="mailto:random@user.org">mail</a>.</p>
<p>This is some <a href="tel:123456789">phone number</a>.</p>
<p>This is some <a href="tel:123456789">phone number</a> with gallery decorator</p>
</div>

<h2>Automatic decorators</h2>
<div id="editor2">
<p>This is <a href="http://ckeditor.com">CKEditor5</a> from <a href="http://cksource.com">CKSource</a>.</p>
<p>This is <a href="http://ckeditor.com" target="_blank" rel="noopener noreferrer" download="download">CKEditor5</a> from <a href="http://cksource.com">CKSource</a>.</p>
<p>This is <a href="//ckeditor.com">CKEditor5</a> as schemaless url.</p>
<p>This is <a href="#anchor">anchor</a> on this page.</p>
<p>This is some random <a href="ftp://127.0.0.1">ftp address</a>.</p>
Expand Down
13 changes: 5 additions & 8 deletions tests/manual/linkdecorator.js
Expand Up @@ -3,7 +3,7 @@
* For licensing, see LICENSE.md.
*/

/* globals console:false, window, document */
/* globals console:false, window, document, CKEditorInspector */

import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
import Enter from '@ckeditor/ckeditor5-enter/src/enter';
Expand All @@ -16,6 +16,8 @@ import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
// Just to have nicely styles switchbutton;
import '@ckeditor/ckeditor5-theme-lark/theme/ckeditor5-ui/components/list/list.css';

window.editors = {};

ClassicEditor
.create( document.querySelector( '#editor' ), {
plugins: [ Link, Typing, Paragraph, Clipboard, Undo, Enter ],
Expand Down Expand Up @@ -48,10 +50,7 @@ ClassicEditor
}
} )
.then( editor => {
if ( !window.editors ) {
window.editors = {};
}
window.editor = editor;
CKEditorInspector.attach( 'manual', editor );
window.editors.manualDecorators = editor;
} )
.catch( err => {
Expand Down Expand Up @@ -83,9 +82,7 @@ ClassicEditor
}
} )
.then( editor => {
if ( !window.editors ) {
window.editors = {};
}
CKEditorInspector.attach( 'automatic', editor );
window.editors.automaticDecorators = editor;
} )
.catch( err => {
Expand Down
21 changes: 13 additions & 8 deletions tests/manual/linkdecorator.md
Expand Up @@ -4,18 +4,23 @@

1. Should be available for every link.
2. Should be applied to the content only when "Save" was clicked.
3. There should be 3 manual decorators available:
* Open in new a new tab
* Downloadable
* Gallery link
4. State of the decorator switches should reflect the model of the currently selected link.
5. Switch buttons should be focusable (with the tab key), after the URL input. The "save" and "cancel" buttons should be focused last.
3. There should be initially set some decorators over specific links based on source data of the editor:
* `CKEditor5` has: "Open in a new tab"
* `CKSource` has: "Open in a new tab" and "Downloadable"
* `CKEditor5` (schemaless) has: "Gallery"
* `ftp address` has: "Downloadable"
4. There should be 3 manual decorators available:
* Open in new a new tab
* Downloadable
* Gallery link
5. State of the decorator switches should reflect the model of the currently selected link.
6. Switch buttons should be focusable (with the tab key), after the URL input. The "save" and "cancel" buttons should be focused last.

### Automatic decorators (window.editors.automaticDecorators).

1. There should be a default automatic decorator turned on, which adds `target="_blank"` and `rel="noopener noreferrer"` attributes to all external links (links starting with `http://`, `https://` or `//`).
2. There should be no changes to the model or the view of the editors.
3. Decorator data should be added during downcast (run `window.editors.automaticDecorators.getData()` to see how it works).
4. There are 2 additional decorators in this editor:
* phone, which detects all links starting with `tel:` and adds the `phone` CSS class to such link,
* internal, which adds the `internal` CSS class to all links starting with `#`.
* phone, which detects all links starting with `tel:` and adds the `phone` CSS class to such link,
* internal, which adds the `internal` CSS class to all links starting with `#`.

0 comments on commit 4161eb1

Please sign in to comment.