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

Add support for manual decorators. Update link command to support additioanl attributes.

Mateusz Samsel 6 лет назад
Родитель
Сommit
9457f3e9c2
2 измененных файлов с 85 добавлено и 13 удалено
  1. 35 2
      packages/ckeditor5-link/src/linkcommand.js
  2. 50 11
      packages/ckeditor5-link/src/linkediting.js

+ 35 - 2
packages/ckeditor5-link/src/linkcommand.js

@@ -25,6 +25,12 @@ export default class LinkCommand extends Command {
 	 * @member {Object|undefined} #value
 	 */
 
+	constructor( editor ) {
+		super( editor );
+
+		this.customAttributes = new Map();
+	}
+
 	/**
 	 * @inheritDoc
 	 */
@@ -52,10 +58,21 @@ export default class LinkCommand extends Command {
 	 * @fires execute
 	 * @param {String} href Link destination.
 	 */
-	execute( href ) {
+	execute( href, customAttrs = {} ) {
 		const model = this.editor.model;
 		const selection = model.document.selection;
 
+		// Stores information about custom attributes to turn on/off.
+		const truthyCustomAttributes = [];
+		const falsyCustomAttributes = [];
+		Object.entries( customAttrs ).forEach( entriesPair => {
+			if ( entriesPair[ 1 ] ) {
+				truthyCustomAttributes.push( entriesPair[ 0 ] );
+			} else {
+				falsyCustomAttributes.push( entriesPair[ 0 ] );
+			}
+		} );
+
 		model.change( writer => {
 			// If selection is collapsed then update selected link or insert new one at the place of caret.
 			if ( selection.isCollapsed ) {
@@ -64,9 +81,15 @@ export default class LinkCommand extends Command {
 				// When selection is inside text with `linkHref` attribute.
 				if ( selection.hasAttribute( 'linkHref' ) ) {
 					// Then update `linkHref` value.
-					const linkRange = findLinkRange( selection.getFirstPosition(), selection.getAttribute( 'linkHref' ), model );
+					const linkRange = findLinkRange( position, selection.getAttribute( 'linkHref' ), model );
 
 					writer.setAttribute( 'linkHref', href, linkRange );
+					truthyCustomAttributes.forEach( item => {
+						writer.setAttribute( item, true, linkRange );
+					} );
+					falsyCustomAttributes.forEach( item => {
+						writer.removeAttribute( item, linkRange );
+					} );
 
 					// Create new range wrapping changed link.
 					writer.setSelection( linkRange );
@@ -79,6 +102,10 @@ export default class LinkCommand extends Command {
 
 					attributes.set( 'linkHref', href );
 
+					truthyCustomAttributes.forEach( item => {
+						attributes.set( item, true );
+					} );
+
 					const node = writer.createText( href, attributes );
 
 					model.insertContent( node, position );
@@ -93,6 +120,12 @@ export default class LinkCommand extends Command {
 
 				for ( const range of ranges ) {
 					writer.setAttribute( 'linkHref', href, range );
+					truthyCustomAttributes.forEach( item => {
+						writer.setAttribute( item, true, range );
+					} );
+					falsyCustomAttributes.forEach( item => {
+						writer.removeAttribute( item, range );
+					} );
 				}
 			}
 		} );

+ 50 - 11
packages/ckeditor5-link/src/linkediting.js

@@ -18,6 +18,7 @@ import '../theme/link.css';
 
 const HIGHLIGHT_CLASS = 'ck-link_selected';
 const AUTO = 'automatic';
+const MANUAL = 'manual';
 
 /**
  * The link engine feature.
@@ -70,8 +71,26 @@ export default class LinkEditing extends Plugin {
 				}
 			} );
 
+		// Create linking commands.
+		editor.commands.add( 'link', new LinkCommand( editor ) );
+		editor.commands.add( 'unlink', new UnlinkCommand( editor ) );
+
+		const linkDecorators = editor.config.get( 'link.decorators' ) || [];
+		this.enableAutomaticDecorators( linkDecorators.filter( item => item.mode === AUTO ) );
+		this.enableManualDecorators( linkDecorators.filter( item => item.mode === MANUAL ) );
+
+		// Enable two-step caret movement for `linkHref` attribute.
+		bindTwoStepCaretToAttribute( editor.editing.view, editor.model, this, 'linkHref' );
+
+		// Setup highlight over selected link.
+		this._setupLinkHighlight();
+	}
+
+	enableAutomaticDecorators( automaticDecoratorDefinitions ) {
+		const editor = this.editor;
 		const automaticDecorators = new AutomaticDecorators();
 
+		// Adds default decorator for external links.
 		if ( editor.config.get( 'link.targetDecorator' ) ) {
 			automaticDecorators.add( {
 				mode: AUTO,
@@ -86,20 +105,40 @@ export default class LinkEditing extends Plugin {
 			} );
 		}
 
-		const linkDecorators = editor.config.get( 'link.decorators' ) || [];
-		automaticDecorators.add( linkDecorators.filter( item => item.mode === AUTO ) );
-
+		automaticDecorators.add( automaticDecoratorDefinitions );
 		editor.conversion.for( 'downcast' ).add( automaticDecorators.getDispatcher() );
+	}
 
-		// Create linking commands.
-		editor.commands.add( 'link', new LinkCommand( editor ) );
-		editor.commands.add( 'unlink', new UnlinkCommand( editor ) );
-
-		// Enable two-step caret movement for `linkHref` attribute.
-		bindTwoStepCaretToAttribute( editor.editing.view, editor.model, this, 'linkHref' );
+	enableManualDecorators( manualDecoratorDefinitions ) {
+		const editor = this.editor;
+		if ( !manualDecoratorDefinitions.length ) {
+			return;
+		}
 
-		// Setup highlight over selected link.
-		this._setupLinkHighlight();
+		const command = editor.commands.get( 'link' );
+		const attrMap = command.customAttributes;
+
+		manualDecoratorDefinitions.forEach( ( decorator, index ) => {
+			const decoratorName = `linkManualDecorator${ index }`;
+			editor.model.schema.extend( '$text', { allowAttributes: decoratorName } );
+
+			attrMap.set( decoratorName, Object.assign( { value: undefined }, decorator ) );
+			editor.conversion.for( 'downcast' ).attributeToElement( {
+				model: decoratorName,
+				view: ( manualDecoratorName, writer ) => {
+					if ( manualDecoratorName ) {
+						const element = writer.createAttributeElement(
+							'a',
+							attrMap.get( decoratorName ).attributes,
+							{
+								priority: 5
+							}
+						);
+						writer.setCustomProperty( 'link', true, element );
+						return element;
+					}
+				} } );
+		} );
 	}
 
 	/**