|
|
@@ -6,18 +6,13 @@
|
|
|
import {
|
|
|
viewFigureToModel,
|
|
|
createImageAttributeConverter,
|
|
|
- convertHoistableImage,
|
|
|
- hoistImageThroughElement
|
|
|
} from '../../src/image/converters';
|
|
|
import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
|
|
|
import { createImageViewElement } from '../../src/image/imageengine';
|
|
|
import { toImageWidget } from '../../src/image/utils';
|
|
|
import buildModelConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildmodelconverter';
|
|
|
import buildViewConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildviewconverter';
|
|
|
-import ModelElement from '@ckeditor/ckeditor5-engine/src/model/element';
|
|
|
-import ViewEmptyElement from '@ckeditor/ckeditor5-engine/src/view/emptyelement';
|
|
|
-import ViewContainerElement from '@ckeditor/ckeditor5-engine/src/view/containerelement';
|
|
|
-import { convertToModelFragment } from '@ckeditor/ckeditor5-engine/src/conversion/view-to-model-converters';
|
|
|
+import ModelRange from '@ckeditor/ckeditor5-engine/src/model/range';
|
|
|
import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
|
|
|
import { setData as setModelData, getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
|
|
|
|
|
|
@@ -65,9 +60,14 @@ describe( 'Image converters', () => {
|
|
|
|
|
|
dispatcher = editor.data.viewToModel;
|
|
|
dispatcher.on( 'element:figure', viewFigureToModel() );
|
|
|
- dispatcher.on( 'element:img', ( evt, data, consumable ) => {
|
|
|
- if ( consumable.consume( data.input, { name: true, attribute: 'src' } ) ) {
|
|
|
- data.output = new ModelElement( 'image', { src: data.input.getAttribute( 'src' ) } );
|
|
|
+ dispatcher.on( 'element:img', ( evt, data, conversionApi ) => {
|
|
|
+ if ( conversionApi.consumable.consume( data.viewItem, { name: true, attribute: 'src' } ) ) {
|
|
|
+ const image = conversionApi.writer.createElement( 'image', { src: data.viewItem.getAttribute( 'src' ) } );
|
|
|
+
|
|
|
+ conversionApi.writer.insert( image, data.cursorPosition );
|
|
|
+
|
|
|
+ data.modelRange = ModelRange.createOn( image );
|
|
|
+ data.cursorPosition = data.modelRange.end;
|
|
|
|
|
|
imgConverterCalled = true;
|
|
|
}
|
|
|
@@ -97,11 +97,18 @@ describe( 'Image converters', () => {
|
|
|
} );
|
|
|
|
|
|
it( 'should be possible to overwrite', () => {
|
|
|
- dispatcher.on( 'element:figure', ( evt, data, consumable ) => {
|
|
|
- consumable.consume( data.input, { name: true } );
|
|
|
- consumable.consume( data.input.getChild( 0 ), { name: true } );
|
|
|
-
|
|
|
- data.output = new ModelElement( 'myImage', { data: { src: data.input.getChild( 0 ).getAttribute( 'src' ) } } );
|
|
|
+ dispatcher.on( 'element:figure', ( evt, data, conversionApi ) => {
|
|
|
+ conversionApi.consumable.consume( data.viewItem, { name: true } );
|
|
|
+ conversionApi.consumable.consume( data.viewItem.getChild( 0 ), { name: true } );
|
|
|
+
|
|
|
+ const element = conversionApi.writer.createElement( 'myImage', {
|
|
|
+ data: {
|
|
|
+ src: data.viewItem.getChild( 0 ).getAttribute( 'src' )
|
|
|
+ }
|
|
|
+ } );
|
|
|
+ conversionApi.writer.insert( element, data.cursorPosition );
|
|
|
+ data.modelRange = ModelRange.createOn( element );
|
|
|
+ data.cursorPosition = data.modelRange.end;
|
|
|
}, { priority: 'high' } );
|
|
|
|
|
|
editor.setData( '<figure class="image"><img src="foo.png" />xyz</figure>' );
|
|
|
@@ -186,138 +193,4 @@ describe( 'Image converters', () => {
|
|
|
);
|
|
|
} );
|
|
|
} );
|
|
|
-
|
|
|
- // More integration tests are in imageengine.js.
|
|
|
- describe( 'autohoist converters', () => {
|
|
|
- let dispatcher, schema, imgConverterCalled, viewImg, modelDiv, modelParagraph, modelLimit;
|
|
|
-
|
|
|
- beforeEach( () => {
|
|
|
- imgConverterCalled = false;
|
|
|
-
|
|
|
- schema = model.schema;
|
|
|
-
|
|
|
- dispatcher = editor.data.viewToModel;
|
|
|
- dispatcher.on( 'element:img', ( evt, data, consumable ) => {
|
|
|
- if ( !schema.checkChild( data.context, 'image' ) ) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if ( consumable.consume( data.input, { name: true, attribute: 'src' } ) ) {
|
|
|
- data.output = new ModelElement( 'image', { src: data.input.getAttribute( 'src' ) } );
|
|
|
-
|
|
|
- imgConverterCalled = true;
|
|
|
- }
|
|
|
- } );
|
|
|
-
|
|
|
- // Make sure to pass document element to the converter and fire this callback after "normal" image callback.
|
|
|
- dispatcher.on( 'element:img', convertHoistableImage, { priority: 'low' } );
|
|
|
-
|
|
|
- viewImg = new ViewEmptyElement( 'img', { src: 'foo.jpg' } );
|
|
|
-
|
|
|
- modelDiv = new ModelElement( 'div' );
|
|
|
- modelParagraph = new ModelElement( 'paragraph' );
|
|
|
- modelLimit = new ModelElement( 'limit' );
|
|
|
- } );
|
|
|
-
|
|
|
- describe( 'convertHoistableImage', () => {
|
|
|
- it( 'should convert img element using already added converters if it is allowed in any point of given context #1', () => {
|
|
|
- const result = dispatcher.convert( viewImg, { context: [ '$root', 'div', 'paragraph' ] } );
|
|
|
-
|
|
|
- // `result` is a model document fragment.
|
|
|
- expect( result.childCount ).to.equal( 1 );
|
|
|
- expect( result.getChild( 0 ).is( 'image' ) ).to.be.true;
|
|
|
- expect( result.getChild( 0 ).getAttribute( 'src' ) ).to.equal( 'foo.jpg' );
|
|
|
- expect( imgConverterCalled ).to.be.true;
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'should convert img element using already added converters if it is allowed in any point of given context #2', () => {
|
|
|
- const result = dispatcher.convert( viewImg, { context: [ '$root', modelDiv, modelParagraph ] } );
|
|
|
-
|
|
|
- // `result` is a model document fragment.
|
|
|
- expect( result.childCount ).to.equal( 1 );
|
|
|
- expect( result.getChild( 0 ).is( 'image' ) ).to.be.true;
|
|
|
- expect( result.getChild( 0 ).getAttribute( 'src' ) ).to.equal( 'foo.jpg' );
|
|
|
- expect( imgConverterCalled ).to.be.true;
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'should not convert img element if there is no allowed context #1', () => {
|
|
|
- const result = dispatcher.convert( viewImg, { context: [ 'div', 'paragraph' ] } );
|
|
|
-
|
|
|
- // `result` is an empty model document fragment.
|
|
|
- expect( result.childCount ).to.equal( 0 );
|
|
|
- expect( imgConverterCalled ).to.be.false;
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'should not convert img element if there is no allowed context #2', () => {
|
|
|
- const result = dispatcher.convert( viewImg, { context: [ modelDiv, modelParagraph ] } );
|
|
|
-
|
|
|
- // `result` is an empty model document fragment.
|
|
|
- expect( result.childCount ).to.equal( 0 );
|
|
|
- expect( imgConverterCalled ).to.be.false;
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'should not convert img element if allowed context is "above" limiting element #1', () => {
|
|
|
- schema.register( 'limit', { isLimit: true } );
|
|
|
-
|
|
|
- const result = dispatcher.convert( viewImg, { context: [ '$root', 'limit', 'div', 'paragraph' ] } );
|
|
|
-
|
|
|
- // `result` is an empty model document fragment.
|
|
|
- expect( result.childCount ).to.equal( 0 );
|
|
|
- expect( imgConverterCalled ).to.be.false;
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'should not convert img element if allowed context is "above" limiting element #2', () => {
|
|
|
- schema.register( 'limit', { isLimit: true } );
|
|
|
-
|
|
|
- const result = dispatcher.convert( viewImg, { context: [ '$root', modelLimit, modelDiv, modelParagraph ] } );
|
|
|
-
|
|
|
- // `result` is an empty model document fragment.
|
|
|
- expect( result.childCount ).to.equal( 0 );
|
|
|
- expect( imgConverterCalled ).to.be.false;
|
|
|
- } );
|
|
|
- } );
|
|
|
-
|
|
|
- describe( 'hoistImageThroughElement', () => {
|
|
|
- it( 'should hoist img element that was converted by convertHoistableImage', () => {
|
|
|
- schema.register( 'div', { inheritAllFrom: '$block' } );
|
|
|
-
|
|
|
- buildModelConverter().for( editor.data.modelToView, editor.editing.modelToView ).fromElement( 'div' ).toElement( 'div' );
|
|
|
- buildViewConverter().for( editor.data.viewToModel ).fromElement( 'div' ).toElement( 'div' );
|
|
|
-
|
|
|
- // Make sure to fire this callback after "normal" div callback.
|
|
|
- dispatcher.on( 'element:div', hoistImageThroughElement, { priority: 'low' } );
|
|
|
-
|
|
|
- // If img view element is converted it must have been converted thanks to convertHoistableImage,
|
|
|
- // because image is not allowed in div.
|
|
|
- const viewDiv = new ViewContainerElement( 'div', null, [ 'foo', viewImg, 'bar' ] );
|
|
|
-
|
|
|
- const result = dispatcher.convert( viewDiv, { context: [ '$root' ] } );
|
|
|
-
|
|
|
- // `result` is a model document fragment.
|
|
|
- expect( result.childCount ).to.equal( 3 );
|
|
|
- expect( result.getChild( 0 ).is( 'div' ) ).to.be.true;
|
|
|
- expect( result.getChild( 1 ).is( 'image' ) ).to.be.true;
|
|
|
- expect( result.getChild( 2 ).is( 'div' ) ).to.be.true;
|
|
|
- } );
|
|
|
-
|
|
|
- it( 'should work fine with elements that are converted to document fragments', () => {
|
|
|
- // The example here is <p> that contains some text and an <img> and is converted in $root > div context.
|
|
|
- // This way we enable autohoisting for <img> and test how it will work when <p> is converted to model document fragment.
|
|
|
- schema.register( 'div', { inheritAllFrom: '$block' } );
|
|
|
-
|
|
|
- dispatcher.on( 'element:p', convertToModelFragment() );
|
|
|
- dispatcher.on( 'element:p', hoistImageThroughElement, { priority: 'low' } );
|
|
|
-
|
|
|
- const viewDiv = new ViewContainerElement( 'p', null, [ 'foo', viewImg, 'bar' ] );
|
|
|
-
|
|
|
- const result = dispatcher.convert( viewDiv, { context: [ '$root', 'div' ] } );
|
|
|
-
|
|
|
- // `result` is a model document fragment.
|
|
|
- expect( result.childCount ).to.equal( 3 );
|
|
|
- expect( result.getChild( 0 ).is( 'text' ) ).to.be.true;
|
|
|
- expect( result.getChild( 1 ).is( 'image' ) ).to.be.true;
|
|
|
- expect( result.getChild( 2 ).is( 'text' ) ).to.be.true;
|
|
|
- } );
|
|
|
- } );
|
|
|
- } );
|
|
|
} );
|