diff --git a/packages/ckeditor5-source-editing/src/sourceediting.ts b/packages/ckeditor5-source-editing/src/sourceediting.ts index b654f8d5b37..3ef946870d0 100644 --- a/packages/ckeditor5-source-editing/src/sourceediting.ts +++ b/packages/ckeditor5-source-editing/src/sourceediting.ts @@ -150,7 +150,7 @@ export default class SourceEditing extends Plugin { // Update the editor data while calling editor.getData() in the source editing mode. editor.data.on( 'get', () => { if ( this.isSourceEditingMode ) { - this._updateEditorData(); + this.updateEditorData(); } }, { priority: 'high' } ); } @@ -187,6 +187,29 @@ export default class SourceEditing extends Plugin { } } + /** + * Updates the source data in all hidden editing roots. + */ + public updateEditorData(): void { + const editor = this.editor; + const data: Record = {}; + + for ( const [ rootName, domSourceEditingElementWrapper ] of this._replacedRoots ) { + const oldData = this._dataFromRoots.get( rootName ); + const newData = domSourceEditingElementWrapper.dataset.value!; + + // Do not set the data unless some changes have been made in the meantime. + // This prevents empty undo steps after switching to the normal editor. + if ( oldData !== newData ) { + data[ rootName ] = newData; + } + } + + if ( Object.keys( data ).length ) { + editor.data.set( data, { batchType: { isUndoable: true } } ); + } + } + /** * Creates source editing wrappers that replace each editing root. Each wrapper contains the document source from the corresponding * root. @@ -262,7 +285,7 @@ export default class SourceEditing extends Plugin { const editor = this.editor; const editingView = editor.editing.view; - this._updateEditorData(); + this.updateEditorData(); editingView.change( writer => { for ( const [ rootName ] of this._replacedRoots ) { @@ -278,29 +301,6 @@ export default class SourceEditing extends Plugin { editingView.focus(); } - /** - * Updates the source data in all hidden editing roots. - */ - private _updateEditorData(): void { - const editor = this.editor; - const data: Record = {}; - - for ( const [ rootName, domSourceEditingElementWrapper ] of this._replacedRoots ) { - const oldData = this._dataFromRoots.get( rootName ); - const newData = domSourceEditingElementWrapper.dataset.value!; - - // Do not set the data unless some changes have been made in the meantime. - // This prevents empty undo steps after switching to the normal editor. - if ( oldData !== newData ) { - data[ rootName ] = newData; - } - } - - if ( Object.keys( data ).length ) { - editor.data.set( data, { batchType: { isUndoable: true } } ); - } - } - /** * Focuses the textarea containing document source from the first editing root. */ diff --git a/packages/ckeditor5-source-editing/tests/sourceediting.js b/packages/ckeditor5-source-editing/tests/sourceediting.js index 870dd6e997a..c967e2d7c68 100644 --- a/packages/ckeditor5-source-editing/tests/sourceediting.js +++ b/packages/ckeditor5-source-editing/tests/sourceediting.js @@ -514,6 +514,22 @@ describe( 'SourceEditing', () => { } ); } ); + describe( 'updateEditorData', () => { + it( 'should update editor model when called', () => { + button.fire( 'execute' ); + + const domRoot = editor.editing.view.getDomRoot(); + const textarea = domRoot.nextSibling.children[ 0 ]; + + textarea.value = 'bar'; + textarea.dispatchEvent( new Event( 'input' ) ); + + expect( getData( editor.model, { withoutSelection: true } ) ).to.equal( 'Foo' ); + plugin.updateEditorData(); + expect( getData( editor.model, { withoutSelection: true } ) ).to.equal( 'bar' ); + } ); + } ); + describe( 'integration with undo', () => { it( 'should preserve the undo/redo stacks when no changes has been in the source editing mode', () => { editor.model.change( writer => {