Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrated inline images with responsive images (srcset, sizes) #9043

Merged
merged 17 commits into from
Mar 16, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions packages/ckeditor5-image/src/imageresize/imageresizeediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ export default class ImageResizeEditing extends Plugin {
const resizeImageCommand = new ResizeImageCommand( editor );

this._registerSchema();
this._registerConverters();
this._registerConverters( 'image' );
this._registerConverters( 'imageInline' );

// Register `resizeImage` command and add `imageResize` command as an alias for backward compatibility.
editor.commands.add( 'resizeImage', resizeImageCommand );
Expand Down Expand Up @@ -93,13 +94,14 @@ export default class ImageResizeEditing extends Plugin {
* Registers image resize converters.
*
* @private
* @param {'image'|'imageInline'} imageType The type of the image.
*/
_registerConverters() {
_registerConverters( imageType ) {
const editor = this.editor;

// Dedicated converter to propagate image's attribute to the img tag.
editor.conversion.for( 'downcast' ).add( dispatcher =>
dispatcher.on( 'attribute:width:image', ( evt, data, conversionApi ) => {
dispatcher.on( `attribute:width:${ imageType }`, ( evt, data, conversionApi ) => {
if ( !conversionApi.consumable.consume( data.item, evt.name ) ) {
return;
}
Expand Down Expand Up @@ -130,5 +132,19 @@ export default class ImageResizeEditing extends Plugin {
value: viewElement => viewElement.getStyle( 'width' )
}
} );

editor.conversion.for( 'upcast' )
.attributeToAttribute( {
view: {
name: 'span',
styles: {
width: /.+/
}
},
model: {
key: 'width',
value: viewElement => viewElement.getStyle( 'width' )
}
} );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import { Command } from 'ckeditor5/src/core';
import { isImage } from '../image/utils';
import { isImage, isImageInline } from '../image/utils';

/**
* The resize image command. Currently, it only supports the width attribute.
Expand All @@ -22,7 +22,7 @@ export default class ResizeImageCommand extends Command {
refresh() {
const element = this.editor.model.document.selection.getSelectedElement();

this.isEnabled = isImage( element );
this.isEnabled = isImage( element ) || isImageInline( element );

if ( !element || !element.hasAttribute( 'width' ) ) {
this.value = null;
Expand Down
63 changes: 62 additions & 1 deletion packages/ckeditor5-image/tests/imageresize/imageresizeediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe( 'ImageResizeEditing', () => {
} );
} );

describe( 'conversion', () => {
describe( 'conversion (block images)', () => {
beforeEach( async () => {
editor = await createEditor();
} );
Expand Down Expand Up @@ -136,6 +136,67 @@ describe( 'ImageResizeEditing', () => {
} );
} );

describe( 'conversion (inline images)', () => {
beforeEach( async () => {
editor = await createEditor();
} );

it( 'upcasts 100px width correctly', () => {
editor.setData(
`<p>Lorem <span class="image-inline" style="width:100px;"><img src="${ IMAGE_SRC_FIXTURE }"></span> ipsum</p>`
);

expect( editor.model.document.getRoot().getChild( 0 ).getChild( 1 ).getAttribute( 'width' ) ).to.equal( '100px' );
} );

it( 'upcasts 50% width correctly', () => {
editor.setData( `<p>Lorem <span class="image-inline" style="width:50%;"><img src="${ IMAGE_SRC_FIXTURE }"></span> ipsum</p>` );

expect( editor.model.document.getRoot().getChild( 0 ).getChild( 1 ).getAttribute( 'width' ) ).to.equal( '50%' );
} );
oleq marked this conversation as resolved.
Show resolved Hide resolved

it( 'downcasts 100px width correctly', () => {
setData( editor.model, `<paragraph><imageInline src="${ IMAGE_SRC_FIXTURE }" width="100px"></imageInline></paragraph>` );

expect( editor.getData() )
.to.equal(
`<p><img class="image_resized" style="width:100px;" src="${ IMAGE_SRC_FIXTURE }"></p>`
);
} );

it( 'downcasts 50% width correctly', () => {
setData( editor.model, `<paragraph><imageInline src="${ IMAGE_SRC_FIXTURE }" width="50%"></imageInline></paragraph>` );

expect( editor.getData() )
.to.equal( `<p><img class="image_resized" style="width:50%;" src="${ IMAGE_SRC_FIXTURE }"></p>` );
} );

it( 'removes style and extra class when no longer resized', () => {
setData( editor.model, `<paragraph><imageInline src="${ IMAGE_SRC_FIXTURE }" width="50%"></imageInline></paragraph>` );

const imageModel = editor.model.document.getRoot().getChild( 0 ).getChild( 0 );

editor.model.change( writer => {
writer.removeAttribute( 'width', imageModel );
} );

expect( editor.getData() )
.to.equal( `<p><img src="${ IMAGE_SRC_FIXTURE }"></p>` );
} );

it( 'doesn\'t downcast consumed tokens', () => {
editor.conversion.for( 'downcast' ).add( dispatcher =>
dispatcher.on( 'attribute:width:imageInline', ( evt, data, conversionApi ) => {
conversionApi.consumable.consume( data.item, 'attribute:width:imageInline' );
}, { priority: 'high' } )
);
setData( editor.model, `<paragraph><imageInline src="${ IMAGE_SRC_FIXTURE }" width="50%"></imageInline></paragraph>` );

expect( editor.getData() )
.to.equal( `<p><img src="${ IMAGE_SRC_FIXTURE }"></p>` );
} );
} );

describe( 'schema', () => {
beforeEach( async () => {
editor = await createEditor();
Expand Down
64 changes: 62 additions & 2 deletions packages/ckeditor5-image/tests/manual/imageresize.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ <h2>Image (width: 40%)</h2>
<img src="sample.jpg" alt="" />
</figure>

<p>
Lorem ipsum
<span class="image-inline image-style-side" style="width: 40%">
<img src="sample.jpg" alt="" />
</span>
dolor sit amet.
</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id tellus et mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortis leo interdum. </p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id tellus et mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortis leo interdum. </p>

Expand All @@ -20,13 +28,27 @@ <h2>Image (width: not set)</h2>
<img src="sample.jpg" alt="" />
</figure>

<p>
Lorem ipsum
<span class="image-inline">
<img src="sample.jpg" alt="" />
</span>
dolor sit amet.
</p>

<h2>Responsive image (width style: not set, width attribute present on the image)</h2>

<figure class="image">
<img alt="Picture of the Warsaw Old Town." width="4288" srcset="https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_430 430w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_860 860w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_1290 1290w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_1720 1720w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_2150 2150w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_2580 2580w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_3010 3010w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_3440 3440w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_3870 3870w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_4288 4288w" sizes="100vw" src="https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg">
</figure>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id telluset mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortisleo interdum. </p>
<p>
Lorem ipsum
<span class="image-inline">
<img alt="Picture of the Warsaw Old Town." width="4288" srcset="https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_430 430w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_860 860w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_1290 1290w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_1720 1720w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_2150 2150w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_2580 2580w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_3010 3010w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_3440 3440w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_3870 3870w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_4288 4288w" sizes="100vw" src="https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg">
</span>
dolor sit amet.
</p>
</div>

<h1>Fancy editor (padding inside figure)</h1>
Expand All @@ -39,6 +61,14 @@ <h2>Image (width: 40%)</h2>
<img src="sample.jpg" alt="" />
</figure>

<p>
Lorem ipsum
<span class="image-inline image-style-side" style="width: 40%">
<img src="sample.jpg" alt="" />
</span>
dolor sit amet.
</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id tellus et mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortis leo interdum. </p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id tellus et mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortis leo interdum. </p>

Expand All @@ -48,13 +78,27 @@ <h2>Image (width: not set)</h2>
<img src="sample.jpg" alt="" />
</figure>

<p>
Lorem ipsum
<span class="image-inline">
<img src="sample.jpg" alt="" />
</span>
dolor sit amet.
</p>

<h2>Responsive image (width style: not set, width attribute present on the image)</h2>

<figure class="image">
<img alt="Picture of the Warsaw Old Town." width="4288" srcset="https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_430 430w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_860 860w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_1290 1290w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_1720 1720w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_2150 2150w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_2580 2580w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_3010 3010w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_3440 3440w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_3870 3870w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_4288 4288w" sizes="100vw" src="https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg">
</figure>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id telluset mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortisleo interdum. </p>
<p>
Lorem ipsum
<figure class="image">
<img alt="Picture of the Warsaw Old Town." width="4288" srcset="https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_430 430w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_860 860w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_1290 1290w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_1720 1720w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_2150 2150w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_2580 2580w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_3010 3010w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_3440 3440w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_3870 3870w, https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg/w_4288 4288w" sizes="100vw" src="https://33333.cdn.cke-cs.com/0fNqCUeBSal4ENvGfd7K/images/c12cb88e596270d8d963b7c87bef1767880f42d94fb2ec43_warsaw01.jpg">
</figure>
dolor sit amet.
</p>
</div>
</div>

Expand All @@ -67,6 +111,14 @@ <h2>Image (width: 200px)</h2>
<img src="sample.jpg" alt="" />
</figure>

<p>
Lorem ipsum
<span class="image-inline" style="width: 200px">
<img src="sample.jpg" alt="" />
</span>
dolor sit amet.
</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id tellus et mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortis leo interdum.</p>

<h2>Image (width: 10em)</h2>
Expand All @@ -75,5 +127,13 @@ <h2>Image (width: 10em)</h2>
<img src="sample.jpg" alt="" />
</figure>

<p>
Lorem ipsum
<span class="image-inline" style="width: 10em">
<img src="sample.jpg" alt="" />
</span>
dolor sit amet.
</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id tellus et mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortis leo interdum.</p>
</div>
Loading