8
0
Просмотр исходного кода

Added upcast conversion for link manual decorators with default values.

Kuba Niegowski 5 лет назад
Родитель
Сommit
493560cac3

+ 37 - 0
packages/ckeditor5-link/src/linkediting.js

@@ -15,6 +15,8 @@ import AutomaticDecorators from './utils/automaticdecorators';
 import ManualDecorator from './utils/manualdecorator';
 import bindTwoStepCaretToAttribute from '@ckeditor/ckeditor5-engine/src/utils/bindtwostepcarettoattribute';
 import findLinkRange from './findlinkrange';
+import Matcher from '@ckeditor/ckeditor5-engine/src/view/matcher';
+
 import '../theme/link.css';
 
 const HIGHLIGHT_CLASS = 'ck-link_selected';
@@ -187,6 +189,41 @@ export default class LinkEditing extends Plugin {
 					key: decorator.id
 				}
 			} );
+
+			// For a decorator that is enabled by default we must check if it was applied to reflect that in the model.
+			if ( decorator.defaultValue ) {
+				editor.conversion.for( 'upcast' ).add( dispatcher => {
+					const matcher = new Matcher( {
+						name: 'a',
+						attributes: {
+							href: true
+						}
+					} );
+
+					dispatcher.on( 'element', ( evt, data, conversionApi ) => {
+						const matcherResult = matcher.match( data.viewItem );
+
+						if ( !matcherResult ) {
+							return;
+						}
+
+						// We must check if all decorator values are set on view element.
+						const decoratorValue = Object.entries( decorator.attributes ).every( ( [ key, value ] ) => {
+							return matcherResult.element.getAttribute( key ) == value;
+						} );
+
+						// The decorator is applied, model attribute was already up-casted.
+						if ( decoratorValue ) {
+							return;
+						}
+
+						// Set attribute on each item in range according to Schema.
+						for ( const node of Array.from( data.modelRange.getItems() ) ) {
+							conversionApi.writer.setAttribute( decorator.id, false, node );
+						}
+					}, { priority: 'low' } );
+				} );
+			}
 		} );
 	}
 

+ 40 - 0
packages/ckeditor5-link/tests/linkediting.js

@@ -664,6 +664,46 @@ describe( 'LinkEditing', () => {
 					} );
 			} );
 
+			it( 'should upcast attributes from initial data for a manual decorator enabled by default', () => {
+				return 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'
+									},
+									defaultValue: true
+								},
+								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" linkIsExternal="false">Bar</$text>' +
+							'</paragraph>'
+						);
+					} );
+			} );
+
 			it( 'should not upcast partial and incorrect attributes', () => {
 				return VirtualTestEditor
 					.create( {