소스 검색

Fix: Schema should ignore attributes stored in elements by DocumentSelection.

Szymon Cofalik 8 년 전
부모
커밋
a8b389cbd9

+ 11 - 0
packages/ckeditor5-engine/src/model/documentselection.js

@@ -391,6 +391,17 @@ export default class DocumentSelection extends Selection {
 		return storePrefix + key;
 	}
 
+	/**
+	 * Checks whether given attribute key is an attribute stored on an element.
+	 *
+	 * @protected
+	 * @param {String} key
+	 * @returns {Boolean}
+	 */
+	static _isStoreAttributeKey( key ) {
+		return key.indexOf( storePrefix ) == 0;
+	}
+
 	/**
 	 * Internal method for setting `DocumentSelection` attribute. Supports attribute priorities (through `directChange`
 	 * parameter).

+ 8 - 0
packages/ckeditor5-engine/src/model/schema.js

@@ -10,6 +10,7 @@
 import Position from './position';
 import Element from './element';
 import Range from './range';
+import DocumentSelection from './documentselection';
 import clone from '@ckeditor/ckeditor5-utils/src/lib/lodash/clone';
 import isArray from '@ckeditor/ckeditor5-utils/src/lib/lodash/isArray';
 import isString from '@ckeditor/ckeditor5-utils/src/lib/lodash/isString';
@@ -217,6 +218,13 @@ export default class Schema {
 		// Keep in mind that if the query has no attributes, query.attribute was converted to an array
 		// with a single `undefined` value. This fits the algorithm well.
 		for ( const attribute of query.attributes ) {
+			// Skip all attributes that are stored in elements.
+			// This isn't perfect solution but we have to deal with it for now.
+			// `attribute` may have `undefined` value.
+			if ( attribute && DocumentSelection._isStoreAttributeKey( attribute ) ) {
+				continue;
+			}
+
 			let matched = false;
 
 			for ( const schemaItem of schemaItems ) {

+ 10 - 0
packages/ckeditor5-engine/tests/model/documentselection.js

@@ -386,6 +386,16 @@ describe( 'DocumentSelection', () => {
 		} );
 	} );
 
+	describe( '_isStoreAttributeKey', () => {
+		it( 'should return true if given key is a key of an attribute stored in element by DocumentSelection', () => {
+			expect( DocumentSelection._isStoreAttributeKey( fooStoreAttrKey ) ).to.be.true;
+		} );
+
+		it( 'should return false if given key is not a key of an attribute stored in element by DocumentSelection', () => {
+			expect( DocumentSelection._isStoreAttributeKey( 'foo' ) ).to.be.false;
+		} );
+	} );
+
 	// DocumentSelection uses LiveRanges so here are only simple test to see if integration is
 	// working well, without getting into complicated corner cases.
 	describe( 'after applying an operation should get updated and fire events', () => {

+ 10 - 0
packages/ckeditor5-engine/tests/model/schema/schema.js

@@ -242,6 +242,16 @@ describe( 'Schema', () => {
 			it( 'should omit path elements that are added to schema', () => {
 				expect( schema.check( { name: '$inline', inside: '$block new $block' } ) ).to.be.true;
 			} );
+
+			it( 'should ignore attributes stored in elements by document selection', () => {
+				expect( schema.check( { name: '$block', attributes: 'selection:foo', inside: '$root' } ) ).to.be.true;
+			} );
+
+			it( 'should disallow attribute stored in an element if that attribute was explicitly disallowed', () => {
+				schema.disallow( { name: '$block', attributes: [ 'selection:foo' ], inside: '$root' } );
+
+				expect( schema.check( { name: '$block', attributes: [ 'selection:foo' ], inside: '$root' } ) ).to.be.false;
+			} );
 		} );
 
 		describe( 'array of elements as inside', () => {