Skip to content

Commit

Permalink
Merge pull request #13873 from ckeditor/cf/4983
Browse files Browse the repository at this point in the history
Other (editor-multi-root): Multi-root editor will now throw if `EditorConfig#initialData` is mismatched with initial roots set in `MultiRootEditor#create()`.
  • Loading branch information
scofalik authored Apr 12, 2023
2 parents 64adabd + bfd032d commit 9fd5944
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 1 deletion.
45 changes: 44 additions & 1 deletion packages/ckeditor5-editor-multi-root/src/multirooteditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,13 @@ export default class MultiRootEditor extends DataApiMixin( Editor ) {
resolve(
editor.initPlugins()
.then( () => editor.ui.init() )
.then( () => editor.data.init( editor.config.get( 'initialData' )! ) )
.then( () => {
// This is checked directly before setting the initial data,
// as plugins may change `EditorConfig#initialData` value.
editor._verifyRootsWithInitialData();

return editor.data.init( editor.config.get( 'initialData' )! );
} )
.then( () => editor.fire<EditorReadyEvent>( 'ready' ) )
.then( () => editor )
);
Expand All @@ -660,6 +666,43 @@ export default class MultiRootEditor extends DataApiMixin( Editor ) {
* Exposed as static editor field for easier access in editor builds.
*/
public static ContextWatchdog = ContextWatchdog;

/**
* @internal
*/
private _verifyRootsWithInitialData(): void {
const initialData = this.config.get( 'initialData' ) as Record<string, string>;

// Roots that are not in the initial data.
for ( const rootName of this.model.document.getRootNames() ) {
if ( !( rootName in initialData ) ) {
/**
* Editor roots do not match {@link module:core/editor/editorconfig~EditorConfig#initialData `initialData` configuration}.
*
* This can happen for one of the two reasons:
*
* * Configuration error. `sourceElementsOrData` parameter in
* {@link module:editor-multi-root/multirooteditor~MultiRootEditor#create `MultiRootEditor.create()`} contains different
* roots than {@link module:core/editor/editorconfig~EditorConfig#initialData `initialData` configuration}.
* * As the editor was initialized, {@link module:core/editor/editorconfig~EditorConfig#initialData `initialData`}
* configuration value or the state of the editor roots has been changed.
*
* @error multi-root-editor-root-initial-data-mismatch
*/
throw new CKEditorError( 'multi-root-editor-root-initial-data-mismatch', null );
}
}

// Roots that are not in the editor.
for ( const rootName of Object.keys( initialData ) ) {
const root = this.model.document.getRoot( rootName );

if ( !root || !root.isAttached() ) {
// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message
throw new CKEditorError( 'multi-root-editor-root-initial-data-mismatch', null );
}
}
}
}

function getInitialData( sourceElementOrData: HTMLElement | string ): string {
Expand Down
78 changes: 78 additions & 0 deletions packages/ckeditor5-editor-multi-root/tests/multirooteditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,84 @@ describe( 'MultiRootEditor', () => {
.catch( done );
} );

it( 'throws error when initial roots are different than initial data - missing root in initial roots', done => {
MultiRootEditor.create( {
foo: document.createElement( 'div' )
}, {
initialData: {
foo: '<p>Foo</p>',
bar: '<p>Bar</p>'
}
} )
.then(
() => {
expect.fail( 'Multi-root editor should throw an error when initital roots and initial data are mismatched.' );
},
err => {
assertCKEditorError( err, 'multi-root-editor-root-initial-data-mismatch', null );
}
)
.then( done )
.catch( done );
} );

it( 'throws error when initial roots are different than initial data - detached root', done => {
// Artificial fake plugin that simulates a root being removed as the editor is initialized.
class RemoveRoot {
constructor( editor ) {
this.editor = editor;
}

init() {
const rootFoo = this.editor.model.document.getRoot( 'foo' );

rootFoo._isAttached = false;
}
}

MultiRootEditor.create( {
foo: document.createElement( 'div' )
}, {
initialData: {
foo: '<p>Foo</p>'
},
extraPlugins: [
RemoveRoot
]
} )
.then(
() => {
expect.fail( 'Multi-root editor should throw an error when initital roots and initial data are mismatched.' );
},
err => {
assertCKEditorError( err, 'multi-root-editor-root-initial-data-mismatch', null );
}
)
.then( done )
.catch( done );
} );

it( 'throws error when initial roots are different than initial data - missing root in initial data', done => {
MultiRootEditor.create( {
foo: document.createElement( 'div' ),
bar: document.createElement( 'div' )
}, {
initialData: {
foo: '<p>Foo</p>'
}
} )
.then(
() => {
expect.fail( 'Multi-root editor should throw an error when initital roots and initial data are mismatched.' );
},
err => {
assertCKEditorError( err, 'multi-root-editor-root-initial-data-mismatch', null );
}
)
.then( done )
.catch( done );
} );

function test( getElementOrData ) {
it( 'creates an instance which inherits from the MultiRootEditor', () => {
return MultiRootEditor
Expand Down

0 comments on commit 9fd5944

Please sign in to comment.