diff --git a/packages/ckeditor5-autosave/package.json b/packages/ckeditor5-autosave/package.json
index ba3334ceab4..b9f4294ce00 100644
--- a/packages/ckeditor5-autosave/package.json
+++ b/packages/ckeditor5-autosave/package.json
@@ -20,6 +20,7 @@
"@ckeditor/ckeditor5-dev-utils": "^25.4.0",
"@ckeditor/ckeditor5-editor-classic": "^30.0.0",
"@ckeditor/ckeditor5-paragraph": "^30.0.0",
+ "@ckeditor/ckeditor5-source-editing": "^30.0.0",
"@ckeditor/ckeditor5-theme-lark": "^30.0.0",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
diff --git a/packages/ckeditor5-autosave/tests/manual/autosave.js b/packages/ckeditor5-autosave/tests/manual/autosave.js
index 6b9c34e69e4..ff10010e500 100644
--- a/packages/ckeditor5-autosave/tests/manual/autosave.js
+++ b/packages/ckeditor5-autosave/tests/manual/autosave.js
@@ -7,13 +7,16 @@
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
+import SourceEditing from '@ckeditor/ckeditor5-source-editing/src/sourceediting';
import ArticlePluginSet from '@ckeditor/ckeditor5-core/tests/_utils/articlepluginset';
import Autosave from '../../src/autosave';
ClassicEditor
.create( document.querySelector( '#editor' ), {
- plugins: [ ArticlePluginSet, Autosave ],
- toolbar: [ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote', 'undo', 'redo' ],
+ plugins: [ ArticlePluginSet, Autosave, SourceEditing ],
+ toolbar: [
+ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote', 'undo', 'redo', '|', 'sourceEditing'
+ ],
image: {
toolbar: [ 'imageStyle:block', 'imageStyle:side', '|', 'imageTextAlternative' ]
},
diff --git a/packages/ckeditor5-engine/src/controller/datacontroller.js b/packages/ckeditor5-engine/src/controller/datacontroller.js
index e509e0b8988..641709e2187 100644
--- a/packages/ckeditor5-engine/src/controller/datacontroller.js
+++ b/packages/ckeditor5-engine/src/controller/datacontroller.js
@@ -145,6 +145,7 @@ export default class DataController {
this.decorate( 'init' );
this.decorate( 'set' );
+ this.decorate( 'get' );
// Fire the `ready` event when the initialization has completed. Such low-level listener gives possibility
// to plug into the initialization pipeline without interrupting the initialization flow.
@@ -163,6 +164,7 @@ export default class DataController {
* Returns the model's data converted by downcast dispatchers attached to {@link #downcastDispatcher} and
* formatted by the {@link #processor data processor}.
*
+ * @fires get
* @param {Object} [options] Additional configuration for the retrieved data. `DataController` provides two optional
* properties: `rootName` and `trim`. Other properties of this object are specified by various editor features.
* @param {String} [options.rootName='main'] Root name.
@@ -523,6 +525,15 @@ export default class DataController {
*
* @event set
*/
+
+ /**
+ * Event fired after {@link #get get() method} has been run.
+ *
+ * The `get` event is fired by decorated {@link #get} method.
+ * See {@link module:utils/observablemixin~ObservableMixin#decorate} for more information and samples.
+ *
+ * @event get
+ */
}
mix( DataController, ObservableMixin );
diff --git a/packages/ckeditor5-engine/tests/controller/datacontroller.js b/packages/ckeditor5-engine/tests/controller/datacontroller.js
index 3e285e4f952..45bbd3f4cfb 100644
--- a/packages/ckeditor5-engine/tests/controller/datacontroller.js
+++ b/packages/ckeditor5-engine/tests/controller/datacontroller.js
@@ -398,6 +398,16 @@ describe( 'DataController', () => {
downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
} );
+ it( 'should be decorated', () => {
+ const spy = sinon.spy();
+
+ data.on( 'get', spy );
+
+ data.get();
+
+ sinon.assert.calledWithExactly( spy, sinon.match.any, [] );
+ } );
+
it( 'should get paragraph with text', () => {
setData( model, '
Foo
' ); } ); + it( 'should update the editor data after calling editor.getData() in the source editing mode', () => { + const setDataSpy = sinon.spy(); + + editor.data.on( 'set', setDataSpy ); + + button.fire( 'execute' ); + + const domRoot = editor.editing.view.getDomRoot(); + const textarea = domRoot.nextSibling.children[ 0 ]; + + textarea.value = 'foo'; + textarea.dispatchEvent( new Event( 'input' ) ); + + // Trigger getData() while in the source editing mode. + expect( editor.getData() ).to.equal( 'foo
' ); + + textarea.value = 'bar'; + textarea.dispatchEvent( new Event( 'input' ) ); + + // Exit source editing mode. + button.fire( 'execute' ); + + expect( setDataSpy.calledTwice ).to.be.true; + expect( setDataSpy.firstCall.args[ 1 ] ).to.deep.equal( [ + { main: 'foo' }, + { batchType: 'default' } + ] ); + expect( setDataSpy.secondCall.args[ 1 ] ).to.deep.equal( [ + { main: 'bar' }, + { batchType: 'default' } + ] ); + expect( editor.data.get() ).to.equal( 'bar
' ); + } ); + it( 'should insert the formatted HTML source (editor output) into the textarea', () => { button.fire( 'execute' );