Ver código fonte

Changed: improvements for treeModel.Schema.

Szymon Cofalik 9 anos atrás
pai
commit
4c4da38c2e

+ 18 - 26
packages/ckeditor5-engine/src/treemodel/schema.js

@@ -10,15 +10,6 @@ import CKEditorError from '../ckeditorerror.js';
 
 export class SchemaItem {
 	constructor( schema ) {
-		if ( !schema ) {
-			/**
-			 * Schema item must have schema instance.
-			 *
-			 * @error schema-item-no-schema
-			 */
-			throw new CKEditorError( 'schema-item-no-schema: Schema item must have schema instance.' );
-		}
-
 		this._schema = schema;
 		this._allowed = [];
 		this._disallowed = [];
@@ -62,9 +53,9 @@ export class SchemaItem {
 
 		for ( let itemPath of itemPaths ) {
 			for ( let checkName of checkPath ) {
-				let baseChain = this._schema._baseChains[ checkName ];
+				let chain = this._schema._extensionChains.get( checkName );
 
-				if ( baseChain.indexOf( itemPath[ 0 ] ) > -1 ) {
+				if ( chain.indexOf( itemPath[ 0 ] ) > -1 ) {
 					itemPath.shift();
 				}
 			}
@@ -97,16 +88,15 @@ export class SchemaItem {
  */
 export default class Schema {
 	constructor() {
-		this._items = {};
-		this._baseChains = {};
+		this._items = new Map();
+		this._extensionChains = new Map();
+
+		this.registerItem( '$inline', null );
+		this.registerItem( '$block', null );
 
-		this.registerItem( 'inline', null );
-		this.registerItem( 'block', null );
-		this.registerItem( 'root', null );
-		this.registerItem( 'text', 'inline' );
+		this.registerItem( '$text', '$inline' );
 
-		this.allow( { name: 'block', inside: 'root' } );
-		this.allow( { name: 'inline', inside: 'block' } );
+		this.allow( { name: '$inline', inside: '$block' } );
 	}
 
 	allow( query ) {
@@ -127,14 +117,14 @@ export default class Schema {
 			throw new CKEditorError( 'schema-no-item: Item with specified name does not exist in schema.' );
 		}
 
-		return this._items[ itemName ];
+		return this._items.get( itemName );
 	}
 
 	hasItem( itemName ) {
-		return !!this._items[ itemName ];
+		return this._items.has( itemName );
 	}
 
-	registerItem( itemName, baseOn ) {
+	registerItem( itemName, isExtending ) {
 		if ( this.hasItem( itemName ) ) {
 			/**
 			 * Item with specified name already exists in schema.
@@ -144,7 +134,7 @@ export default class Schema {
 			throw new CKEditorError( 'schema-item-exists: Item with specified name already exists in schema.' );
 		}
 
-		if ( !!baseOn && !this.hasItem( baseOn ) ) {
+		if ( !!isExtending && !this.hasItem( isExtending ) ) {
 			/**
 			 * Item with specified name does not exist in schema.
 			 *
@@ -153,8 +143,10 @@ export default class Schema {
 			throw new CKEditorError( 'schema-no-item: Item with specified name does not exist in schema.' );
 		}
 
-		this._items[ itemName ] = new SchemaItem( this );
-		this._baseChains[ itemName ] = this.hasItem( baseOn ) ? this._baseChains[ baseOn ].concat( itemName ) : [ itemName ];
+		this._items.set( itemName, new SchemaItem( this ) );
+
+		const chain = this.hasItem( isExtending ) ? this._extensionChains.get( isExtending ).concat( itemName ) : [ itemName ];
+		this._extensionChains.set( itemName, chain );
 	}
 
 	checkAtPosition( query, position ) {
@@ -174,7 +166,7 @@ export default class Schema {
 
 		path = ( typeof path === 'string' ) ? path.split( ' ' ) : path;
 
-		const schemaItems = this._baseChains[ query.name ].map( ( name ) => {
+		const schemaItems = this._extensionChains.get( query.name ).map( ( name ) => {
 			return this._getItem( name );
 		} );
 

+ 8 - 13
packages/ckeditor5-engine/tests/treemodel/schema/schema.js

@@ -26,7 +26,6 @@ describe( 'constructor', () => {
 
 		expect( schema.registerItem.calledWithExactly( '$inline', null ) );
 		expect( schema.registerItem.calledWithExactly( '$block', null ) );
-		expect( schema.registerItem.calledWithExactly( '$root', null ) );
 
 		Schema.prototype.registerItem.restore();
 	} );
@@ -34,10 +33,6 @@ describe( 'constructor', () => {
 	it( 'should allow inline in block', () => {
 		expect( schema.checkForPath( { name: '$inline' }, [ '$block' ] ) ).to.be.true;
 	} );
-
-	it( 'should allow block in root', () => {
-		expect( schema.checkForPath( { name: '$block' }, [ '$root' ] ) ).to.be.true;
-	} );
 } );
 
 describe( 'registerItem', () => {
@@ -53,10 +48,10 @@ describe( 'registerItem', () => {
 		schema.registerItem( 'secondB', 'first' );
 		schema.registerItem( 'third', 'secondA' );
 
-		expect( schema._baseChains.first ).to.deep.equal( [ 'first' ] );
-		expect( schema._baseChains.secondA ).to.deep.equal( [ 'first', 'secondA' ] );
-		expect( schema._baseChains.secondB ).to.deep.equal( [ 'first', 'secondB' ] );
-		expect( schema._baseChains.third ).to.deep.equal( [ 'first', 'secondA', 'third' ] );
+		expect( schema._extensionChains.get( 'first' ) ).to.deep.equal( [ 'first' ] );
+		expect( schema._extensionChains.get( 'secondA' ) ).to.deep.equal( [ 'first', 'secondA' ] );
+		expect( schema._extensionChains.get( 'secondB' ) ).to.deep.equal( [ 'first', 'secondB' ] );
+		expect( schema._extensionChains.get( 'third' ) ).to.deep.equal( [ 'first', 'secondA', 'third' ] );
 	} );
 
 	it( 'should make registered item inherit allows from base item', () => {
@@ -139,7 +134,7 @@ describe( 'checkAtPosition', () => {
 
 	beforeEach( () => {
 		doc = new Document();
-		root = doc.createRoot( 'root' );
+		root = doc.createRoot( 'root', 'div' );
 
 		root.insertChildren( 0, [
 			new Element( 'div' ),
@@ -176,12 +171,12 @@ describe( 'checkAtPosition', () => {
 
 		// Header is allowed in DIV.
 		expect( schema.checkAtPosition( { name: 'header' }, new Position( root, [ 0, 0 ] ) ) ).to.be.true;
+
+		// Inline is allowed in block and root is DIV, which is block.
+		expect( schema.checkAtPosition( { name: '$inline' }, new Position( root, [ 0 ] ) ) ).to.be.true;
 	} );
 
 	it( 'should return false if given element is not allowed by schema at given position', () => {
-		// Inline is not allowed in root.
-		expect( schema.checkAtPosition( { name: '$inline' }, new Position( root, [ 0 ] ) ) ).to.be.false;
-
 		// P with attribute is not allowed anywhere.
 		expect( schema.checkAtPosition( { name: 'p', attribute: 'bold' }, new Position( root, [ 0 ] ) ) ).to.be.false;
 		expect( schema.checkAtPosition( { name: 'p', attribute: 'bold' }, new Position( root, [ 0, 0 ] ) ) ).to.be.false;

+ 8 - 7
packages/ckeditor5-engine/tests/treemodel/schema/schemaitem.js

@@ -7,7 +7,6 @@
 
 import Schema from '/ckeditor5/core/treemodel/schema.js';
 import { SchemaItem as SchemaItem } from '/ckeditor5/core/treemodel/schema.js';
-import CKEditorError from '/ckeditor5/core/ckeditorerror.js';
 
 let schema, item;
 
@@ -31,12 +30,6 @@ describe( 'constructor', () => {
 		expect( item._disallowed ).to.deep.equal( [] );
 		expect( item._allowed ).to.deep.equal( [] );
 	} );
-
-	it( 'should throw if no schema was passed', () => {
-		expect( () => {
-			new SchemaItem();
-		} ).to.throw( CKEditorError, /schema-item-no-schema/ );
-	} );
 } );
 
 describe( 'addAllowed', () => {
@@ -167,3 +160,11 @@ describe( '_hasMatchingPath', () => {
 		expect( item._hasMatchingPath( 'DISALLOW', [ 'html', 'div', 'p', 'header', 'span' ], 'bold' ) ).to.be.true;
 	} );
 } );
+
+describe( 'toJSON', () => {
+	it( 'should create proper JSON string', () => {
+		let parsedItem = JSON.parse( JSON.stringify( item ) );
+
+		expect( parsedItem._schema ).to.equal( '[treeModel.Schema]' );
+	} );
+} );