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

Introduced util for checking whether the editor wasn't initialized on the same element more than once #176

Merged
merged 10 commits into from
Jul 23, 2019
47 changes: 47 additions & 0 deletions src/editor/utils/securesourceelement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';

/**
* @module core/editor/utils/securesourceelement
*/

const SECURE_ATTRIBUTE = 'data-ckeditor5';

/**
* Checks if the editor was initialized using a source element. If yes, it prevents to creating another editor
jodator marked this conversation as resolved.
Show resolved Hide resolved
* using the same source element. In other words, you cannot use the same source element more than once.
*
* @param {module:core/editor/editor~Editor} editor Editor instance.
*/
export default function secureSourceElement( editor ) {
const sourceElement = editor.sourceElement;

// If the editor was initialized without specifying an element, we don't need to secure anything.
if ( !sourceElement ) {
return;
}

if ( sourceElement.hasAttribute( SECURE_ATTRIBUTE ) ) {
/**
* An element passed to the editor creator has been passed more than once. The element can be used only once.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* An element passed to the editor creator has been passed more than once. The element can be used only once.
* Another editor instance was already initialized on this element. You cannot create more then one editor on the same element.

Or something similar - I get the feeling that the error description should reflect how someone could use our API. So it is rather creating two or more instances of the ediotr on some element then passing something.

*
* @error securesourceelement-source-element-used-more-than-once
*/
throw new CKEditorError(
'securesourceelement-source-element-used-more-than-once: ' +
jodator marked this conversation as resolved.
Show resolved Hide resolved
'The editor cannot be initialized using the same source element more than once.'
);
ma2ciek marked this conversation as resolved.
Show resolved Hide resolved
}

// Mark the source element.
sourceElement.setAttribute( SECURE_ATTRIBUTE, 'true' );

// Remove the attribute when the editor is being destroyed.
jodator marked this conversation as resolved.
Show resolved Hide resolved
editor.once( 'destroy', () => {
sourceElement.removeAttribute( SECURE_ATTRIBUTE );
} );
}
69 changes: 69 additions & 0 deletions tests/editor/utils/securesourceelement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

/* global document */

import secureSourceElement from '../../../src/editor/utils/securesourceelement';
import Editor from '../../../src/editor/editor';
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';

describe( 'secureSourceElement()', () => {
let editor, sourceElement;

beforeEach( () => {
class CustomEditor extends Editor {}

sourceElement = document.createElement( 'div' );
editor = new CustomEditor();

editor.sourceElement = sourceElement;
editor.state = 'ready';
} );

afterEach( () => {
if ( editor ) {
return editor.destroy();
}
} );

it( 'does nothing if the editor was not initialized using the source element', () => {
delete editor.sourceElement;

expect( () => {
secureSourceElement( editor );
} ).to.not.throw();
} );

it( 'does nothing if the editor was initialized using the element for the first time', () => {
expect( () => {
secureSourceElement( editor );
} ).to.not.throw();
} );

it( 'sets the data attribute after initializing the editor', () => {
secureSourceElement( editor );

expect( sourceElement.hasAttribute( 'data-ckeditor5' ) ).to.equal( true );
} );

it( 'removes the data attribute after destroying the editor', () => {
secureSourceElement( editor );

return editor.destroy()
.then( () => {
editor = null;

expect( sourceElement.hasAttribute( 'data-ckeditor5' ) ).to.equal( false );
} );
} );

it( 'throws an error if the same element was used twice', () => {
sourceElement.setAttribute( 'data-ckeditor5', 'true' );
jodator marked this conversation as resolved.
Show resolved Hide resolved

expect( () => {
ma2ciek marked this conversation as resolved.
Show resolved Hide resolved
secureSourceElement( editor );
} ).to.throw( CKEditorError, /^securesourceelement-source-element-used-more-than-once/ );
} );
} );