diff --git a/packages/ckeditor5-image/src/image/converters.ts b/packages/ckeditor5-image/src/image/converters.ts index e9ff6c94a9b..484cd43e657 100644 --- a/packages/ckeditor5-image/src/image/converters.ts +++ b/packages/ckeditor5-image/src/image/converters.ts @@ -249,9 +249,18 @@ export function downcastSourcesAttribute( imageUtils: ImageUtils ): ( dispatcher viewElement = parentElement; } - // Insert the picture and move img into it. - viewWriter.insert( viewWriter.createPositionBefore( imgElement ), pictureElement ); - viewWriter.move( viewWriter.createRangeOn( imgElement ), viewWriter.createPositionAt( pictureElement, 'end' ) ); + const prevPictureElement = imgElement.parent!.is( 'element', 'picture' ) ? imgElement.parent : null; + + if ( prevPictureElement ) { + // Insert a new picture, move img into it, remove previous picture element (ckeditor5#17192). + viewWriter.insert( viewWriter.createPositionBefore( prevPictureElement ), pictureElement ); + viewWriter.move( viewWriter.createRangeOn( imgElement ), viewWriter.createPositionAt( pictureElement, 'end' ) ); + viewWriter.remove( prevPictureElement ); + } else { + // Insert the picture and move img into it. + viewWriter.insert( viewWriter.createPositionBefore( imgElement ), pictureElement ); + viewWriter.move( viewWriter.createRangeOn( imgElement ), viewWriter.createPositionAt( pictureElement, 'end' ) ); + } // Apply collected attribute elements over the new picture element. for ( const attributeElement of attributeElements ) { diff --git a/packages/ckeditor5-image/tests/pictureediting.js b/packages/ckeditor5-image/tests/pictureediting.js index 5cde35b7e0e..9ba942c9f96 100644 --- a/packages/ckeditor5-image/tests/pictureediting.js +++ b/packages/ckeditor5-image/tests/pictureediting.js @@ -1857,6 +1857,94 @@ describe( 'PictureEditing', () => { expect( editor.getData() ).to.equal( '

foobar

' ); } ); + + it( 'should downcast changed "sources" attribute on an existing picture element', () => { + editor.setData( + '
' + + '' + + '' + + '' + + '' + + '
Caption
' + + '
' + ); + + model.change( writer => { + writer.setAttribute( + 'sources', + [ + { + srcset: '/assets/sample2.png' + } + ], + modelDocument.getRoot().getChild( 0 ) + ); + } ); + + expect( getViewData( view, { withoutSelection: true } ) ).to.equal( + '
' + + '' + + '' + + '' + + '' + + '
' + + 'Caption' + + '
' + + '
' + ); + } ); + + it( 'should downcast changed "sources" attribute on an existing linked picture element', () => { + editor.setData( + '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '
Caption
' + + '
' + ); + + model.change( writer => { + writer.setAttribute( + 'sources', + [ + { + srcset: '/assets/sample2.png' + } + ], + modelDocument.getRoot().getChild( 0 ) + ); + } ); + + expect( getViewData( view, { withoutSelection: true } ) ).to.equal( + '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '
' + + 'Caption' + + '
' + + '
' + ); + } ); } ); } ); } );