Kaynağa Gözat

Added defaultValue to ManualDecorators.

Kuba Niegowski 5 yıl önce
ebeveyn
işleme
25c3e9187a

+ 1 - 0
packages/ckeditor5-link/src/link.js

@@ -215,4 +215,5 @@ export default class Link extends Plugin {
  * @property {Object} attributes Key-value pairs used as link attributes added to the output during the
  * {@glink framework/guides/architecture/editing-engine#conversion downcasting}.
  * Attributes should follow the {@link module:engine/view/elementdefinition~ElementDefinition} syntax.
+ * @property {Boolean} [defaultValue=false] Controls whether the decorator is "on" by default.
  */

+ 29 - 20
packages/ckeditor5-link/src/linkcommand.js

@@ -46,7 +46,7 @@ export default class LinkCommand extends Command {
 	 */
 	restoreManualDecoratorStates() {
 		for ( const manualDecorator of this.manualDecorators ) {
-			manualDecorator.value = this._getDecoratorStateFromModel( manualDecorator.id );
+			manualDecorator.value = this._getDecoratorStateFromModel( manualDecorator );
 		}
 	}
 
@@ -60,7 +60,7 @@ export default class LinkCommand extends Command {
 		this.value = doc.selection.getAttribute( 'linkHref' );
 
 		for ( const manualDecorator of this.manualDecorators ) {
-			manualDecorator.value = this._getDecoratorStateFromModel( manualDecorator.id );
+			manualDecorator.value = this._getDecoratorStateFromModel( manualDecorator );
 		}
 
 		this.isEnabled = model.schema.checkAttributeInSelection( doc.selection, 'linkHref' );
@@ -132,14 +132,18 @@ export default class LinkCommand extends Command {
 		const model = this.editor.model;
 		const selection = model.document.selection;
 		// Stores information about manual decorators to turn them on/off when command is applied.
-		const truthyManualDecorators = [];
-		const falsyManualDecorators = [];
+		const setManualDecorators = [];
+		const removeManualDecorators = [];
 
 		for ( const name in manualDecoratorIds ) {
-			if ( manualDecoratorIds[ name ] ) {
-				truthyManualDecorators.push( name );
+			const manualDecorator = this.manualDecorators.get( name );
+			const value = manualDecoratorIds[ name ];
+
+			// We need to set an attribute for the disabled decorator if it's enabled by default (`defaultValue`).
+			if ( value || value != manualDecorator.defaultValue ) {
+				setManualDecorators.push( { name, value } );
 			} else {
-				falsyManualDecorators.push( name );
+				removeManualDecorators.push( name );
 			}
 		}
 
@@ -155,12 +159,12 @@ export default class LinkCommand extends Command {
 
 					writer.setAttribute( 'linkHref', href, linkRange );
 
-					truthyManualDecorators.forEach( item => {
-						writer.setAttribute( item, true, linkRange );
+					setManualDecorators.forEach( ( { name, value } ) => {
+						writer.setAttribute( name, value, linkRange );
 					} );
 
-					falsyManualDecorators.forEach( item => {
-						writer.removeAttribute( item, linkRange );
+					removeManualDecorators.forEach( name => {
+						writer.removeAttribute( name, linkRange );
 					} );
 
 					// Create new range wrapping changed link.
@@ -174,8 +178,8 @@ export default class LinkCommand extends Command {
 
 					attributes.set( 'linkHref', href );
 
-					truthyManualDecorators.forEach( item => {
-						attributes.set( item, true );
+					setManualDecorators.forEach( ( { name, value } ) => {
+						attributes.set( name, value );
 					} );
 
 					const node = writer.createText( href, attributes );
@@ -193,12 +197,12 @@ export default class LinkCommand extends Command {
 				for ( const range of ranges ) {
 					writer.setAttribute( 'linkHref', href, range );
 
-					truthyManualDecorators.forEach( item => {
-						writer.setAttribute( item, true, range );
+					setManualDecorators.forEach( ( { name, value } ) => {
+						writer.setAttribute( name, value, range );
 					} );
 
-					falsyManualDecorators.forEach( item => {
-						writer.removeAttribute( item, range );
+					removeManualDecorators.forEach( name => {
+						writer.removeAttribute( name, range );
 					} );
 				}
 			}
@@ -209,11 +213,16 @@ export default class LinkCommand extends Command {
 	 * Provides information whether a decorator with a given name is present in the currently processed selection.
 	 *
 	 * @private
-	 * @param {String} decoratorName The name of the manual decorator used in the model
+	 * @param {module:link/utils~ManualDecorator} decorator The manual decorator used in the model.
 	 * @returns {Boolean} The information whether a given decorator is currently present in the selection.
 	 */
-	_getDecoratorStateFromModel( decoratorName ) {
+	_getDecoratorStateFromModel( decorator ) {
 		const doc = this.editor.model.document;
-		return doc.selection.getAttribute( decoratorName ) || false;
+
+		if ( doc.selection.hasAttribute( decorator.id ) ) {
+			return doc.selection.getAttribute( decorator.id );
+		}
+
+		return decorator.defaultValue;
 	}
 }

+ 9 - 1
packages/ckeditor5-link/src/utils/manualdecorator.js

@@ -27,8 +27,9 @@ export default class ManualDecorator {
 	 * @param {String} config.label The label used in the user interface to toggle the manual decorator.
 	 * @param {Object} config.attributes A set of attributes added to output data when the decorator is active for a specific link.
 	 * Attributes should keep the format of attributes defined in {@link module:engine/view/elementdefinition~ElementDefinition}.
+	 * @param {Boolean} [config.defaultValue=false] Controls whether the decorator is "on" by default.
 	 */
-	constructor( { id, label, attributes } ) {
+	constructor( { id, label, attributes, defaultValue } ) {
 		/**
 		 * An ID of a manual decorator which is the name of the attribute in the model, for example: 'linkManualDecorator0'.
 		 *
@@ -45,6 +46,13 @@ export default class ManualDecorator {
 		this.set( 'value' );
 
 		/**
+		 * The default value of manual decorator.
+		 *
+		 * @type {Boolean}
+		 */
+		this.defaultValue = defaultValue || false;
+
+		/**
 		 * The label used in the user interface to toggle the manual decorator.
 		 *
 		 * @type {String}

+ 76 - 15
packages/ckeditor5-link/tests/linkcommand.js

@@ -284,10 +284,18 @@ describe( 'LinkCommand', () => {
 							target: '_blank'
 						}
 					} ) );
+					command.manualDecorators.add( new ManualDecorator( {
+						id: 'linkIsSth',
+						label: 'Sth',
+						attributes: {
+							class: 'sth'
+						},
+						defaultValue: true
+					} ) );
 
 					model.schema.extend( '$text', {
 						allowIn: '$root',
-						allowAttributes: [ 'linkHref', 'linkIsFoo', 'linkIsBar' ]
+						allowAttributes: [ 'linkHref', 'linkIsFoo', 'linkIsBar', 'linkIsSth' ]
 					} );
 
 					model.schema.register( 'p', { inheritAllFrom: '$block' } );
@@ -302,19 +310,19 @@ describe( 'LinkCommand', () => {
 			it( 'should insert additional attributes to link when it is created', () => {
 				setData( model, 'foo[]bar' );
 
-				command.execute( 'url', { linkIsFoo: true, linkIsBar: true } );
+				command.execute( 'url', { linkIsFoo: true, linkIsBar: true, linkIsSth: true } );
 
 				expect( getData( model ) ).to
-					.equal( 'foo[<$text linkHref="url" linkIsBar="true" linkIsFoo="true">url</$text>]bar' );
+					.equal( 'foo[<$text linkHref="url" linkIsBar="true" linkIsFoo="true" linkIsSth="true">url</$text>]bar' );
 			} );
 
 			it( 'should add additional attributes to link when link is modified', () => {
 				setData( model, 'f<$text linkHref="url">o[]oba</$text>r' );
 
-				command.execute( 'url', { linkIsFoo: true, linkIsBar: true } );
+				command.execute( 'url', { linkIsFoo: true, linkIsBar: true, linkIsSth: true } );
 
 				expect( getData( model ) ).to
-					.equal( 'f[<$text linkHref="url" linkIsBar="true" linkIsFoo="true">ooba</$text>]r' );
+					.equal( 'f[<$text linkHref="url" linkIsBar="true" linkIsFoo="true" linkIsSth="true">ooba</$text>]r' );
 			} );
 
 			it( 'should remove additional attributes to link if those are falsy', () => {
@@ -324,25 +332,33 @@ describe( 'LinkCommand', () => {
 
 				expect( getData( model ) ).to.equal( 'foo[<$text linkHref="url">url</$text>]bar' );
 			} );
+
+			it( 'should add additional attributes to link if those are falsy but decorator\'s defaultValue is set to true', () => {
+				setData( model, 'foo<$text linkHref="url" linkIsBar="true" linkIsFoo="true">u[]rl</$text>bar' );
+
+				command.execute( 'url', { linkIsFoo: false, linkIsBar: false, linkIsSth: false } );
+
+				expect( getData( model ) ).to.equal( 'foo[<$text linkHref="url" linkIsSth="false">url</$text>]bar' );
+			} );
 		} );
 
 		describe( 'range selection', () => {
 			it( 'should insert additional attributes to link when it is created', () => {
 				setData( model, 'f[ooba]r' );
 
-				command.execute( 'url', { linkIsFoo: true, linkIsBar: true } );
+				command.execute( 'url', { linkIsFoo: true, linkIsBar: true, linkIsSth: true } );
 
 				expect( getData( model ) ).to
-					.equal( 'f[<$text linkHref="url" linkIsBar="true" linkIsFoo="true">ooba</$text>]r' );
+					.equal( 'f[<$text linkHref="url" linkIsBar="true" linkIsFoo="true" linkIsSth="true">ooba</$text>]r' );
 			} );
 
 			it( 'should add additional attributes to link when link is modified', () => {
 				setData( model, 'f[<$text linkHref="foo">ooba</$text>]r' );
 
-				command.execute( 'url', { linkIsFoo: true, linkIsBar: true } );
+				command.execute( 'url', { linkIsFoo: true, linkIsBar: true, linkIsSth: true } );
 
 				expect( getData( model ) ).to
-					.equal( 'f[<$text linkHref="url" linkIsBar="true" linkIsFoo="true">ooba</$text>]r' );
+					.equal( 'f[<$text linkHref="url" linkIsBar="true" linkIsFoo="true" linkIsSth="true">ooba</$text>]r' );
 			} );
 
 			it( 'should remove additional attributes to link if those are falsy', () => {
@@ -352,29 +368,66 @@ describe( 'LinkCommand', () => {
 
 				expect( getData( model ) ).to.equal( 'foo[<$text linkHref="url">url</$text>]bar' );
 			} );
+
+			it( 'should add additional attributes to link if those are falsy but decorator\'s defaultValue is set to true', () => {
+				setData( model, 'foo[<$text linkHref="url" linkIsBar="true" linkIsFoo="true">url</$text>]bar' );
+
+				command.execute( 'url', { linkIsFoo: false, linkIsBar: false, linkIsSth: false } );
+
+				expect( getData( model ) ).to.equal( 'foo[<$text linkHref="url" linkIsSth="false">url</$text>]bar' );
+			} );
 		} );
 
 		describe( 'restoreManualDecoratorStates()', () => {
 			it( 'synchronize values with current model state', () => {
-				setData( model, 'foo<$text linkHref="url" linkIsBar="true" linkIsFoo="true">u[]rl</$text>bar' );
+				setData( model, 'foo<$text linkHref="url" linkIsBar="true" linkIsFoo="true" linkIsSth="true">u[]rl</$text>bar' );
 
 				expect( decoratorStates( command.manualDecorators ) ).to.deep.equal( {
 					linkIsFoo: true,
-					linkIsBar: true
+					linkIsBar: true,
+					linkIsSth: true
 				} );
 
 				command.manualDecorators.first.value = false;
 
 				expect( decoratorStates( command.manualDecorators ) ).to.deep.equal( {
 					linkIsFoo: false,
-					linkIsBar: true
+					linkIsBar: true,
+					linkIsSth: true
+				} );
+
+				command.restoreManualDecoratorStates();
+
+				expect( decoratorStates( command.manualDecorators ) ).to.deep.equal( {
+					linkIsFoo: true,
+					linkIsBar: true,
+					linkIsSth: true
+				} );
+			} );
+
+			it( 'synchronize values with current model state when the decorator that is "on" default is "off"', () => {
+				setData( model, 'foo<$text linkHref="url" linkIsBar="true" linkIsFoo="true" linkIsSth="false">u[]rl</$text>bar' );
+
+				expect( decoratorStates( command.manualDecorators ) ).to.deep.equal( {
+					linkIsFoo: true,
+					linkIsBar: true,
+					linkIsSth: false
+				} );
+
+				command.manualDecorators.last.value = true;
+
+				expect( decoratorStates( command.manualDecorators ) ).to.deep.equal( {
+					linkIsFoo: true,
+					linkIsBar: true,
+					linkIsSth: true
 				} );
 
 				command.restoreManualDecoratorStates();
 
 				expect( decoratorStates( command.manualDecorators ) ).to.deep.equal( {
 					linkIsFoo: true,
-					linkIsBar: true
+					linkIsBar: true,
+					linkIsSth: false
 				} );
 			} );
 		} );
@@ -383,8 +436,16 @@ describe( 'LinkCommand', () => {
 			it( 'obtain current values from the model', () => {
 				setData( model, 'foo[<$text linkHref="url" linkIsBar="true">url</$text>]bar' );
 
-				expect( command._getDecoratorStateFromModel( 'linkIsFoo' ) ).to.be.false;
-				expect( command._getDecoratorStateFromModel( 'linkIsBar' ) ).to.be.true;
+				expect( command._getDecoratorStateFromModel( command.manualDecorators.get( 'linkIsFoo' ) ) ).to.be.false;
+				expect( command._getDecoratorStateFromModel( command.manualDecorators.get( 'linkIsBar' ) ) ).to.be.true;
+			} );
+
+			it( 'fallbacks to defaultValue if there is no attribute in model', () => {
+				setData( model, 'foo[<$text linkHref="url">url</$text>]bar' );
+
+				expect( command._getDecoratorStateFromModel( command.manualDecorators.get( 'linkIsFoo' ) ) ).to.be.false;
+				expect( command._getDecoratorStateFromModel( command.manualDecorators.get( 'linkIsBar' ) ) ).to.be.false;
+				expect( command._getDecoratorStateFromModel( command.manualDecorators.get( 'linkIsSth' ) ) ).to.be.true;
 			} );
 		} );
 	} );

+ 17 - 0
packages/ckeditor5-link/tests/utils/manualdecorator.js

@@ -24,6 +24,23 @@ describe( 'Manual Decorator', () => {
 		expect( manualDecorator.id ).to.equal( 'foo' );
 		expect( manualDecorator.label ).to.equal( 'bar' );
 		expect( manualDecorator.attributes ).to.deep.equal( { one: 'two' } );
+		expect( manualDecorator.defaultValue ).to.deep.equal( false );
+	} );
+
+	it( 'constructor with defaultValue', () => {
+		manualDecorator = new ManualDecorator( {
+			id: 'foo',
+			label: 'bar',
+			attributes: {
+				one: 'two'
+			},
+			defaultValue: true
+		} );
+
+		expect( manualDecorator.id ).to.equal( 'foo' );
+		expect( manualDecorator.label ).to.equal( 'bar' );
+		expect( manualDecorator.attributes ).to.deep.equal( { one: 'two' } );
+		expect( manualDecorator.defaultValue ).to.deep.equal( true );
 	} );
 
 	it( '#value is observable', () => {