Procházet zdrojové kódy

Allow to get external plugin by name.

Oskar Wróbel před 6 roky
rodič
revize
9ef2ad14a1

+ 30 - 4
packages/ckeditor5-core/src/context.js

@@ -12,7 +12,17 @@ import PluginCollection from './plugincollection';
 import Locale from '@ckeditor/ckeditor5-utils/src/locale';
 import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
 
+/**
+ * @TODO
+ */
 export default class Context {
+	/**
+	 * Creates a context instance with a given configuration.
+	 *
+	 * Usually, not to be used directly. See the static {@link ~Context.create `create()`} method.
+	 *
+	 * @param {Object} [config={}] The context config.
+	 */
 	constructor( config ) {
 		/**
 		 * Holds all configurations specific to this context instance.
@@ -28,13 +38,13 @@ export default class Context {
 		 * @readonly
 		 * @type {module:core/plugincollection~PluginCollection}
 		 */
-		this.plugins = new PluginCollection( this, this.config.get( 'plugins' ) );
+		this.plugins = new PluginCollection( this );
 
 		const languageConfig = this.config.get( 'language' ) || {};
 
 		/**
 		 * @readonly
-		 * @member {module:utils/locale~Locale}
+		 * @type {module:utils/locale~Locale}
 		 */
 		this.locale = new Locale( {
 			uiLanguage: typeof languageConfig === 'string' ? languageConfig : languageConfig.ui,
@@ -42,7 +52,7 @@ export default class Context {
 		} );
 
 		/**
-		 * List of editors used with this context.
+		 * List of editors to which this context instance is injected.
 		 *
 		 * @private
 		 * @type {Set<module:core/editor/editor~Editor>}
@@ -51,6 +61,8 @@ export default class Context {
 	}
 
 	/**
+	 * Adds a reference to the to which context is injected.
+	 *
 	 * @param {module:core/editor/editor~Editor} editor
 	 */
 	addEditor( editor ) {
@@ -58,14 +70,22 @@ export default class Context {
 	}
 
 	/**
+	 * Removes a reference to the editor to which context was injected.
+	 *
 	 * @param {module:core/editor/editor~Editor} editor
 	 */
 	removeEditor( editor ) {
 		return this._editors.delete( editor );
 	}
 
+	/**
+	 * Loads and initializes plugins specified in the config.
+	 *
+	 * @returns {Promise.<module:core/plugin~LoadedPlugins>} A promise which resolves
+	 * once the initialization is completed providing an array of loaded plugins.
+	 */
 	initPlugins() {
-		const plugins = this.config.get( 'plugins' );
+		const plugins = this.config.get( 'plugins' ) || [];
 
 		for ( const plugin of plugins ) {
 			if ( typeof plugin != 'function' ) {
@@ -93,6 +113,12 @@ export default class Context {
 			.then( () => this.plugins.destroy() );
 	}
 
+	/**
+	 * @TODO
+	 *
+	 * @param {Object} [config] The context config.
+	 * @returns {Promise} A promise resolved once the context is ready. The promise resolves with the created context instance.
+	 */
 	static create( config ) {
 		return new Promise( resolve => {
 			const context = new this( config );

+ 6 - 3
packages/ckeditor5-core/src/plugincollection.js

@@ -55,15 +55,13 @@ export default class PluginCollection {
 		this._availablePlugins = new Map();
 
 		for ( const PluginConstructor of availablePlugins ) {
-			this._availablePlugins.set( PluginConstructor, PluginConstructor );
-
 			if ( PluginConstructor.pluginName ) {
 				this._availablePlugins.set( PluginConstructor.pluginName, PluginConstructor );
 			}
 		}
 
 		/**
-		 * List of constructors of externally loaded plugins.
+		 * Map of external plugins which can be retrieved by their constructors or instance.
 		 *
 		 * @private
 		 * @type {Map<Function,Function>}
@@ -73,6 +71,11 @@ export default class PluginCollection {
 		for ( const [ PluginConstructor, pluginInstance ] of externalPlugins ) {
 			this._externalPlugins.set( PluginConstructor, pluginInstance );
 			this._externalPlugins.set( pluginInstance, PluginConstructor );
+
+			// To make it possible to require plugin by its name.
+			if ( PluginConstructor.pluginName ) {
+				this._availablePlugins.set( PluginConstructor.pluginName, PluginConstructor );
+			}
 		}
 	}
 

+ 34 - 5
packages/ckeditor5-core/tests/context.js

@@ -76,7 +76,7 @@ describe( 'Context', () => {
 		await context.destroy();
 	} );
 
-	it( 'should not destroy context plugin when only the editor is destroyed', async () => {
+	it( 'should not destroy context along with the editor when context is injected to the editor', async () => {
 		const contextPluginDestroySpy = sinon.spy();
 		const editorPluginDestroySpy = sinon.spy();
 
@@ -101,15 +101,44 @@ describe( 'Context', () => {
 		sinon.assert.notCalled( contextPluginDestroySpy );
 	} );
 
-	it( 'should not destroy context along with editor when context is injected to the editor', () => {
+	it( 'should destroy all editors with injected context when context is destroyed', async () => {
+		const context = await Context.create();
+		const editorA = await VirtualTestEditor.create( { context } );
+		const editorB = await VirtualTestEditor.create( { context } );
+		const editorC = await VirtualTestEditor.create();
 
-	} );
+		sinon.spy( editorA, 'destroy' );
+		sinon.spy( editorB, 'destroy' );
+		sinon.spy( editorC, 'destroy' );
 
-	it( 'should destroy all editors along with the context when context is injected to them', () => {
+		await context.destroy();
 
+		sinon.assert.calledOnce( editorA.destroy );
+		sinon.assert.calledOnce( editorB.destroy );
+		sinon.assert.notCalled( editorC.destroy );
 	} );
 
-	it( 'should destroy context along with editor when context is created by the editor', () => {
+	it( 'should be able to add context plugin to the editor using pluginName property', async () => {
+		class ContextPluginA extends Plugin {
+			static get pluginName() {
+				return 'ContextPluginA';
+			}
+		}
+
+		class ContextPluginB extends Plugin {
+			static get pluginName() {
+				return 'ContextPluginB';
+			}
+
+			static get requires() {
+				return [ ContextPluginA ];
+			}
+		}
+
+		const context = await Context.create( { plugins: [ ContextPluginB ] } );
+		const editor = await VirtualTestEditor.create( { context, plugins: [ 'ContextPluginA' ] } );
 
+		expect( editor.plugins.has( ContextPluginA ) ).to.equal( true );
+		expect( editor.plugins.has( ContextPluginB ) ).to.equal( false );
 	} );
 } );