Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge pull request #23 from ckeditor/t/22
Browse files Browse the repository at this point in the history
Feature: Added support for multi-root editors. Closes #22.
  • Loading branch information
Piotr Jasiun committed Aug 14, 2019
2 parents 1a47364 + 6b06aef commit 692955e
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 6 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"devDependencies": {
"@ckeditor/ckeditor5-core": "^12.2.1",
"@ckeditor/ckeditor5-editor-classic": "^12.1.3",
"@ckeditor/ckeditor5-engine": "^13.2.1",
"@ckeditor/ckeditor5-paragraph": "^11.0.4",
"eslint": "^5.5.0",
"eslint-config-ckeditor5": "^2.0.0",
Expand Down
29 changes: 23 additions & 6 deletions src/watchdog.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,10 @@ export default class Watchdog {
*/

/**
* The latest saved editor data.
* The latest saved editor data represented as a root name -> root data object.
*
* @private
* @member {String} #_data
* @member {Object.<String,String>} #_data
*/

/**
Expand All @@ -154,7 +154,7 @@ export default class Watchdog {
* The editor source element or data.
*
* @private
* @member {HTMLElement|String} #_elementOrData
* @member {HTMLElement|String|Object.<String|String>} #_elementOrData
*/

/**
Expand Down Expand Up @@ -203,7 +203,7 @@ export default class Watchdog {
* Creates a watched editor instance using the creator passed to the {@link #setCreator `setCreator()`} method or
* {@link module:watchdog/watchdog~Watchdog.for `Watchdog.for()`} helper.
*
* @param {HTMLElement|String} elementOrData
* @param {HTMLElement|String|Object.<String|String>} elementOrData
* @param {module:core/editor/editorconfig~EditorConfig} [config]
*
* @returns {Promise}
Expand Down Expand Up @@ -257,7 +257,8 @@ export default class Watchdog {
this.listenTo( editor.model.document, 'change:data', this._throttledSave );

this._lastDocumentVersion = editor.model.document.version;
this._data = editor.data.get();

this._data = this._getData();
this.state = 'ready';
} );
}
Expand Down Expand Up @@ -311,7 +312,7 @@ export default class Watchdog {
}

try {
this._data = this._editor.data.get();
this._data = this._getData();
this._lastDocumentVersion = version;
} catch ( err ) {
console.error(
Expand All @@ -322,6 +323,22 @@ export default class Watchdog {
}
}

/**
* Returns the editor data.
*
* @private
* @returns {Object<String,String>}
*/
_getData() {
const data = {};

for ( const rootName of this._editor.model.document.getRootNames() ) {
data[ rootName ] = this._editor.data.get( { rootName } );
}

return data;
}

/**
* Checks if the error comes from the editor that is handled by the watchdog (by checking the error context) and
* restarts the editor. It reacts to {@link module:utils/ckeditorerror~CKEditorError `CKEditorError` errors} only.
Expand Down
61 changes: 61 additions & 0 deletions tests/watchdog.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
/* globals setTimeout, window, console, document */

import Watchdog from '../src/watchdog';
import Editor from '@ckeditor/ckeditor5-core/src/editor/editor';
import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import { expectToThrowCKEditorError } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
import HtmlDataProcessor from '@ckeditor/ckeditor5-engine/src/dataprocessor/htmldataprocessor';

describe( 'Watchdog', () => {
let element;
Expand Down Expand Up @@ -989,6 +991,65 @@ describe( 'Watchdog', () => {
} );
} );
} );

describe( 'multi-root editors', () => {
it( 'should support multi-root editors', () => {
class MultiRootEditor extends Editor {
constructor( sourceElements, config ) {
super( config );

this.data.processor = new HtmlDataProcessor();

// Create a root for each source element.
for ( const rootName of Object.keys( sourceElements ) ) {
this.model.document.createRoot( '$root', rootName );
}
}

static async create( sourceElements, config ) {
const editor = new this( sourceElements, config );

await editor.initPlugins();

await editor.data.init( config.initialData );

editor.fire( 'ready' );

return editor;
}
}

const watchdog = Watchdog.for( MultiRootEditor );

// sinon.stub( window, 'onerror' ).value( undefined ); and similar do not work.
const originalErrorHandler = window.onerror;
window.onerror = undefined;

return watchdog
.create( {
header: element
}, {
initialData: {
header: '<p>Foo</p>'
},
plugins: [ Paragraph ]
} )
.then( () => {
expect( watchdog.editor.data.get( { rootName: 'header' } ) ).to.equal( '<p>Foo</p>' );

setTimeout( () => throwCKEditorError( 'foo', watchdog.editor ) );

return new Promise( res => {
window.onerror = originalErrorHandler;
expect( watchdog.editor.data.get( { rootName: 'header' } ) ).to.equal( '<p>Foo</p>' );

res();
} );
} ).then( () => {
return watchdog.destroy();
} );
} );
} );
} );

function throwCKEditorError( name, context ) {
Expand Down

0 comments on commit 692955e

Please sign in to comment.