Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge pull request #1221 from ckeditor/t/532
Browse files Browse the repository at this point in the history
Other: Rewritten the Schema API. Closes #532.
  • Loading branch information
Reinmar authored Jan 1, 2018
2 parents aea6119 + f7d2c80 commit 4e4f5c3
Show file tree
Hide file tree
Showing 40 changed files with 3,483 additions and 2,135 deletions.
2 changes: 1 addition & 1 deletion src/controller/datacontroller.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import ModelRange from '../model/range';
* * {@link module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher model to view} and
* * {@link module:engine/conversion/viewconversiondispatcher~ViewConversionDispatcher view to model} converters.
*
* @mixes module:utils/emittermixin~ObservableMixin
* @mixes module:utils/observablemixin~ObservableMixin
*/
export default class DataController {
/**
Expand Down
16 changes: 2 additions & 14 deletions src/conversion/buildviewconverter.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,7 @@ class ViewConverterBuilder {
continue;
}

// Check whether generated structure is okay with `Schema`.
const keys = Array.from( modelElement.getAttributeKeys() );

if ( !conversionApi.schema.check( { name: modelElement.name, attributes: keys, inside: data.context } ) ) {
if ( !conversionApi.schema.checkChild( data.context, modelElement ) ) {
continue;
}

Expand Down Expand Up @@ -518,16 +515,7 @@ function setAttributeOn( toChange, attribute, data, conversionApi ) {
return;
}

const keys = Array.from( toChange.getAttributeKeys() );
keys.push( attribute.key );

const schemaQuery = {
name: toChange.name || '$text',
attributes: keys,
inside: data.context
};

if ( conversionApi.schema.check( schemaQuery ) ) {
if ( conversionApi.schema.checkAttribute( toChange, attribute.key ) ) {
conversionApi.writer.setAttribute( attribute.key, attribute.value, toChange );
}
}
Expand Down
7 changes: 1 addition & 6 deletions src/conversion/view-to-model-converters.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,7 @@ export function convertToModelFragment() {
*/
export function convertText() {
return ( evt, data, consumable, conversionApi ) => {
const schemaQuery = {
name: '$text',
inside: data.context
};

if ( conversionApi.schema.check( schemaQuery ) ) {
if ( conversionApi.schema.checkChild( data.context, '$text' ) ) {
if ( consumable.consume( data.input ) ) {
data.output = conversionApi.writer.createText( data.input.data );
}
Expand Down
8 changes: 2 additions & 6 deletions src/conversion/viewconversiondispatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,8 @@ import log from '@ckeditor/ckeditor5-utils/src/log';
* // Converter for paragraphs (<p>).
* viewDispatcher.on( 'element:p', ( evt, data, consumable, conversionApi ) => {
* const paragraph = new ModelElement( 'paragraph' );
* const schemaQuery = {
* name: 'paragraph',
* inside: data.context
* };
*
* if ( conversionApi.schema.check( schemaQuery ) ) {
* if ( conversionApi.schema.checkChild( data.context, paragraph ) ) {
* if ( !consumable.consume( data.input, { name: true } ) ) {
* // Before converting this paragraph's children we have to update their context by this paragraph.
* data.context.push( paragraph );
Expand All @@ -81,7 +77,7 @@ import log from '@ckeditor/ckeditor5-utils/src/log';
* inside: data.context
* };
*
* if ( conversionApi.schema.check( schemaQuery ) ) {
* if ( conversionApi.schema.checkAttribute( [ ...data.context, '$text' ], 'link' ) ) {
* item.setAttribute( 'link', data.input.getAttribute( 'href' ) );
* }
* }
Expand Down
23 changes: 7 additions & 16 deletions src/dev-utils/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ export function stringify( node, selectionOrPositionOrRange = null ) {
* @param {Object} [options={}] Additional configuration.
* @param {Array<Object>} [options.selectionAttributes] List of attributes which will be passed to the selection.
* @param {Boolean} [options.lastRangeBackward=false] If set to true last range will be added as backward.
* @param {module:engine/model/schema~SchemaPath} [options.context=[ '$root' ]] The conversion context.
* @param {module:engine/model/schema~SchemaContextDefinition} [options.context=[ '$root' ]] The conversion context.
* If not provided default `[ '$root' ]` will be used.
* @returns {module:engine/model/element~Element|module:engine/model/text~Text|
* module:engine/model/documentfragment~DocumentFragment|Object} Returns parsed model node or
Expand Down Expand Up @@ -329,14 +329,10 @@ function convertToModelFragment() {

function convertToModelElement() {
return ( evt, data, consumable, conversionApi ) => {
const schemaQuery = {
name: data.input.name,
attributes: Array.from( data.input.getAttributeKeys() ),
inside: data.context
};

if ( !conversionApi.schema.check( schemaQuery ) ) {
throw new Error( `Element '${ schemaQuery.name }' not allowed in context ${ JSON.stringify( data.context ) }.` );
const elementName = data.input.name;

if ( !conversionApi.schema.checkChild( data.context, elementName ) ) {
throw new Error( `Element '${ elementName }' was not allowed in context ${ JSON.stringify( data.context ) }.` );
}

// View attribute value is a string so we want to typecast it to the original type.
Expand All @@ -356,13 +352,8 @@ function convertToModelElement() {

function convertToModelText( withAttributes = false ) {
return ( evt, data, consumable, conversionApi ) => {
const schemaQuery = {
name: '$text',
inside: data.context
};

if ( !conversionApi.schema.check( schemaQuery ) ) {
throw new Error( `Element '${ schemaQuery.name }' not allowed in context ${ JSON.stringify( data.context ) }.` );
if ( !conversionApi.schema.checkChild( data.context, '$text' ) ) {
throw new Error( `Text was not allowed in context ${ JSON.stringify( data.context ) }.` );
}

let node;
Expand Down
6 changes: 3 additions & 3 deletions src/model/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ export default class Document {
const schema = this.model.schema;

// Return collapsed range if provided position is valid.
if ( schema.check( { name: '$text', inside: position } ) ) {
if ( schema.checkChild( position, '$text' ) ) {
return new Range( position );
}

Expand All @@ -266,11 +266,11 @@ export default class Document {
const type = ( data.walker == backwardWalker ? 'elementEnd' : 'elementStart' );
const value = data.value;

if ( value.type == type && schema.objects.has( value.item.name ) ) {
if ( value.type == type && schema.isObject( value.item ) ) {
return Range.createOn( value.item );
}

if ( schema.check( { name: '$text', inside: value.nextPosition } ) ) {
if ( schema.checkChild( value.nextPosition, '$text' ) ) {
return new Range( value.nextPosition );
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/model/documentselection.js
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ export default class DocumentSelection extends Selection {
// ...look for a first character node in that range and take attributes from it.
for ( const value of range ) {
// If the item is an object, we don't want to get attributes from its children.
if ( value.item.is( 'element' ) && schema.objects.has( value.item.name ) ) {
if ( value.item.is( 'element' ) && schema.isObject( value.item ) ) {
break;
}

Expand Down
21 changes: 20 additions & 1 deletion src/model/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import getSelectedContent from './utils/getselectedcontent';
* {@link module:engine/model/model~Model#document}, and all detached nodes, used to data manipulation. All of them are
* created and modified by the {@link module:engine/model/writer~Writer}, which can be get using
* {@link module:engine/model/model~Model#change} or {@link module:engine/model/model~Model#enqueueChange} methods.
*
* @mixes module:utils/observablemixin~ObservableMixin
*/
export default class Model {
constructor() {
Expand Down Expand Up @@ -68,6 +70,23 @@ export default class Model {

[ 'insertContent', 'deleteContent', 'modifySelection', 'getSelectedContent', 'applyOperation' ]
.forEach( methodName => this.decorate( methodName ) );

// Register some default abstract entities.
this.schema.register( '$root', {
isLimit: true
} );
this.schema.register( '$block', {
allowIn: '$root',
isBlock: true
} );
this.schema.register( '$text', {
allowIn: '$block'
} );
this.schema.register( '$clipboardHolder', {
allowContentOf: '$root',
isLimit: true
} );
this.schema.extend( '$text', { allowIn: '$clipboardHolder' } );
}

/**
Expand Down Expand Up @@ -296,7 +315,7 @@ export default class Model {

for ( const item of rangeOrElement.getItems() ) {
// Remember, `TreeWalker` returns always `textProxy` nodes.
if ( item.is( 'textProxy' ) || this.schema.objects.has( item.name ) ) {
if ( item.is( 'textProxy' ) || this.schema.isObject( item ) ) {
return true;
}
}
Expand Down
Loading

0 comments on commit 4e4f5c3

Please sign in to comment.