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 #262 from ckeditor/t/ckeditor5-table/99
Browse files Browse the repository at this point in the history
Feature: Enable image in table cells.
  • Loading branch information
scofalik committed Dec 20, 2018
2 parents 09f1e82 + 56fbe79 commit 3a4d2ca
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 30 deletions.
25 changes: 13 additions & 12 deletions src/image/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ export function isImageAllowed( model ) {
const schema = model.schema;
const selection = model.document.selection;

return isImageAllowedInParent( selection, schema, model ) && checkSelectionWithObject( selection, schema );
return isImageAllowedInParent( selection, schema, model ) &&
!checkSelectionOnObject( selection, schema ) &&
isInOtherImage( selection );
}

// Checks if image is allowed by schema in optimal insertion parent.
Expand All @@ -112,29 +114,28 @@ function isImageAllowedInParent( selection, schema, model ) {
return schema.checkChild( parent, 'image' );
}

// Check used in image commands for additional cases when the command should be disabled:
//
// - selection is on object
// - selection is inside object
// Check if selection is on object.
//
// @returns {Boolean}
function checkSelectionWithObject( selection, schema ) {
function checkSelectionOnObject( selection, schema ) {
const selectedElement = selection.getSelectedElement();

const isSelectionOnObject = !!selectedElement && schema.isObject( selectedElement );
const isSelectionInObject = !![ ...selection.focus.getAncestors() ].find( ancestor => schema.isObject( ancestor ) );
return selectedElement && schema.isObject( selectedElement );
}

return !isSelectionOnObject && !isSelectionInObject;
// Checks if selection is placed in other image (ie. in caption).
function isInOtherImage( selection ) {
return [ ...selection.focus.getAncestors() ].every( ancestor => !ancestor.is( 'image' ) );
}

// Returns a node that will be used to insert image with `model.insertContent` to check if image can be placed there.
function getInsertImageParent( selection, model ) {
const insertAt = findOptimalInsertionPosition( selection, model );

let parent = insertAt.parent;
const parent = insertAt.parent;

if ( !parent.is( '$root' ) ) {
parent = parent.parent;
if ( parent.isEmpty && !parent.is( '$root' ) ) {
return parent.parent;
}

return parent;
Expand Down
29 changes: 23 additions & 6 deletions tests/image/imageinsertcommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,30 @@ describe( 'ImageInsertCommand', () => {
expect( command.isEnabled ).to.be.false;
} );

it( 'should be false when the selection is inside other object', () => {
model.schema.register( 'object', { isObject: true, allowIn: '$root' } );
model.schema.extend( '$text', { allowIn: 'object' } );
editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'object', view: 'object' } ) );
setModelData( model, '<object>[]</object>' );
it( 'should be true when the selection is inside isLimit element which allows image', () => {
model.schema.register( 'outerObject', { isObject: true, isBlock: true, allowIn: '$root' } );
model.schema.register( 'limit', { isLimit: true, allowIn: 'outerObject' } );
model.schema.extend( '$block', { allowIn: 'limit' } );

expect( command.isEnabled ).to.be.false;
editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'outerObject', view: 'outerObject' } ) );
editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'limit', view: 'limit' } ) );

setModelData( model, '<outerObject><limit>[]</limit></outerObject>' );

expect( command.isEnabled ).to.be.true;
} );

it( 'should be true when the selection is inside isLimit element which allows image', () => {
model.schema.register( 'outerObject', { isObject: true, isBlock: true, allowIn: '$root' } );
model.schema.register( 'limit', { isLimit: true, allowIn: 'outerObject' } );
model.schema.extend( '$block', { allowIn: 'limit' } );

editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'outerObject', view: 'outerObject' } ) );
editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'limit', view: 'limit' } ) );

setModelData( model, '<outerObject><limit><paragraph>foo[]</paragraph></limit></outerObject>' );

expect( command.isEnabled ).to.be.true;
} );

it( 'should be false when schema disallows image', () => {
Expand Down
29 changes: 23 additions & 6 deletions tests/image/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,30 @@ describe( 'image widget utils', () => {
expect( isImageAllowed( model ) ).to.be.false;
} );

it( 'should return false when the selection is inside other object', () => {
model.schema.register( 'object', { isObject: true, allowIn: '$root' } );
model.schema.extend( '$text', { allowIn: 'object' } );
editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'object', view: 'object' } ) );
setModelData( model, '<object>[]</object>' );
it( 'should be true when the selection is inside isLimit element which allows image', () => {
model.schema.register( 'outerObject', { isObject: true, isBlock: true, allowIn: '$root' } );
model.schema.register( 'limit', { isLimit: true, allowIn: 'outerObject' } );
model.schema.extend( '$block', { allowIn: 'limit' } );

expect( isImageAllowed( model ) ).to.be.false;
editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'outerObject', view: 'outerObject' } ) );
editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'limit', view: 'limit' } ) );

setModelData( model, '<outerObject><limit>[]</limit></outerObject>' );

expect( isImageAllowed( model ) ).to.be.true;
} );

it( 'should be true when the selection is inside isLimit element which allows image', () => {
model.schema.register( 'outerObject', { isObject: true, isBlock: true, allowIn: '$root' } );
model.schema.register( 'limit', { isLimit: true, allowIn: 'outerObject' } );
model.schema.extend( '$block', { allowIn: 'limit' } );

editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'outerObject', view: 'outerObject' } ) );
editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'limit', view: 'limit' } ) );

setModelData( model, '<outerObject><limit><paragraph>foo[]</paragraph></limit></outerObject>' );

expect( isImageAllowed( model ) ).to.be.true;
} );

it( 'should return false when schema disallows image', () => {
Expand Down
29 changes: 23 additions & 6 deletions tests/imageupload/imageuploadcommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,30 @@ describe( 'ImageUploadCommand', () => {
expect( command.isEnabled ).to.be.false;
} );

it( 'should be false when the selection is inside other object', () => {
model.schema.register( 'object', { isObject: true, allowIn: '$root' } );
model.schema.extend( '$text', { allowIn: 'object' } );
editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'object', view: 'object' } ) );
setModelData( model, '<object>[]</object>' );
it( 'should be true when the selection is inside isLimit element which allows image', () => {
model.schema.register( 'outerObject', { isObject: true, isBlock: true, allowIn: '$root' } );
model.schema.register( 'limit', { isLimit: true, allowIn: 'outerObject' } );
model.schema.extend( '$block', { allowIn: 'limit' } );

expect( command.isEnabled ).to.be.false;
editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'outerObject', view: 'outerObject' } ) );
editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'limit', view: 'limit' } ) );

setModelData( model, '<outerObject><limit>[]</limit></outerObject>' );

expect( command.isEnabled ).to.be.true;
} );

it( 'should be true when the selection is inside isLimit element which allows image', () => {
model.schema.register( 'outerObject', { isObject: true, isBlock: true, allowIn: '$root' } );
model.schema.register( 'limit', { isLimit: true, allowIn: 'outerObject' } );
model.schema.extend( '$block', { allowIn: 'limit' } );

editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'outerObject', view: 'outerObject' } ) );
editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'limit', view: 'limit' } ) );

setModelData( model, '<outerObject><limit><paragraph>foo[]</paragraph></limit></outerObject>' );

expect( command.isEnabled ).to.be.true;
} );

it( 'should be false when schema disallows image', () => {
Expand Down

0 comments on commit 3a4d2ca

Please sign in to comment.