diff --git a/packages/ckeditor5-engine/src/view/domconverter.js b/packages/ckeditor5-engine/src/view/domconverter.js index f7df2243ecc..dbc70201155 100644 --- a/packages/ckeditor5-engine/src/view/domconverter.js +++ b/packages/ckeditor5-engine/src/view/domconverter.js @@ -680,7 +680,7 @@ export default class DomConverter { const attrs = domNode.attributes; if ( attrs ) { - for ( let i = attrs.length - 1; i >= 0; i-- ) { + for ( let l = attrs.length, i = 0; i < l; i++ ) { viewElement._setAttribute( attrs[ i ].name, attrs[ i ].value ); } } diff --git a/packages/ckeditor5-engine/tests/view/domconverter/dom-to-view.js b/packages/ckeditor5-engine/tests/view/domconverter/dom-to-view.js index d5d2506820b..9f5b6efd57f 100644 --- a/packages/ckeditor5-engine/tests/view/domconverter/dom-to-view.js +++ b/packages/ckeditor5-engine/tests/view/domconverter/dom-to-view.js @@ -206,6 +206,22 @@ describe( 'DomConverter', () => { expect( viewComment ).to.be.null; } ); + it( 'should set attributes in the same order as in the DOM', () => { + const domP = createElement( document, 'p', { 'data-foo': 'a', 'data-bar': 'b' } ); + const viewP = converter.domToView( domP ); + + expect( viewP ).to.be.an.instanceof( ViewElement ); + expect( viewP.name ).to.equal( 'p' ); + + const attributes = Array.from( viewP.getAttributes() ); + + expect( attributes.length ).to.equal( 2 ); + expect( attributes ).to.deep.equal( [ + [ 'data-foo', 'a' ], + [ 'data-bar', 'b' ] + ] ); + } ); + describe( 'it should clear whitespaces', () => { it( 'at the beginning of block element', () => { const domDiv = createElement( document, 'div', {}, [ diff --git a/packages/ckeditor5-html-support/tests/datafilter.js b/packages/ckeditor5-html-support/tests/datafilter.js index 006485b88d4..40d15e81773 100644 --- a/packages/ckeditor5-html-support/tests/datafilter.js +++ b/packages/ckeditor5-html-support/tests/datafilter.js @@ -605,6 +605,24 @@ describe( 'DataFilter', () => { ); } ); + it( 'should not change order of attributes', () => { + dataFilter.allowElement( 'section' ); + dataFilter.allowAttributes( { + name: 'section', + attributes: true + } ); + + editor.setData( '

foobar

' ); + + expect( getModelData( model, { withoutSelection: true } ) ).to.deep.equal( + 'foobar' + ); + + expect( editor.getData() ).to.equal( + '

foobar

' + ); + } ); + it( 'should disallow attributes', () => { dataFilter.allowElement( 'section' ); dataFilter.allowAttributes( { name: 'section', attributes: { 'data-foo': /[\s\S]+/ } } ); @@ -1765,7 +1783,7 @@ describe( 'DataFilter', () => { } ); expect( editor.getData() ).to.equal( - '

' + '

' ); } ); @@ -2346,7 +2364,7 @@ describe( 'DataFilter', () => { } ); expect( editor.getData() ).to.equal( - '

foobar

' + '

foobar

' ); } ); diff --git a/packages/ckeditor5-html-support/tests/integrations/mediaembed.js b/packages/ckeditor5-html-support/tests/integrations/mediaembed.js index e5562ea75db..51a77f02e32 100644 --- a/packages/ckeditor5-html-support/tests/integrations/mediaembed.js +++ b/packages/ckeditor5-html-support/tests/integrations/mediaembed.js @@ -1159,7 +1159,7 @@ describe( 'MediaEmbedElementSupport', () => { } ); expect( editor.getData() ).to.equal( - '

' + '

' ); } ); @@ -1278,7 +1278,7 @@ describe( 'MediaEmbedElementSupport', () => { expect( editor.getData() ).to.equal( '
' + - '

' + + '

' + '
' ); diff --git a/packages/ckeditor5-html-support/tests/integrations/table.js b/packages/ckeditor5-html-support/tests/integrations/table.js index a99fa283fe2..2f1b8fe3f9c 100644 --- a/packages/ckeditor5-html-support/tests/integrations/table.js +++ b/packages/ckeditor5-html-support/tests/integrations/table.js @@ -925,14 +925,14 @@ describe( 'TableElementSupport', () => { expect( editor.getData() ).to.equalMarkup( '
' + '' + - '' + + '' + '' + '' + '' + '' + - '' + - '' + - '' + + '' + + '' + + '' + '' + '' + '
Bar
Foo
Foo
' +