8
0

plugincollection.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /**
  2. * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. 'use strict';
  6. /**
  7. * Manages a list of CKEditor plugins, including loading, initialization and destruction.
  8. *
  9. * @class PluginCollection
  10. * @extends Collection
  11. */
  12. CKEDITOR.define( [
  13. 'collection',
  14. 'plugin',
  15. 'ckeditorerror',
  16. 'log'
  17. ], ( Collection, Plugin, CKEditorError, log ) => {
  18. class PluginCollection extends Collection {
  19. /**
  20. * Creates an instance of the PluginCollection class, initializing it with a set of plugins.
  21. *
  22. * @constructor
  23. */
  24. constructor( editor ) {
  25. super( { idProperty: 'name' } );
  26. this._editor = editor;
  27. }
  28. /**
  29. * Loads a set of plugins and add them to the collection.
  30. *
  31. * @param {String} plugins A comma separated list of plugin names to get loaded.
  32. * @returns {Promise} A promise which gets resolved once all plugins are loaded and available into the
  33. * collection.
  34. * @param {core/Plugin[]} returns.loadedPlugins The array of loaded plugins.
  35. */
  36. load( plugins ) {
  37. // The list of plugins which are being loaded (to avoid circular references issues).
  38. const loading = {};
  39. // Plugins added to the collection (for the purpose of returning an array of loaded plugins).
  40. const loaded = [];
  41. // It may happen that an empty list was passed – don't fail.
  42. plugins = plugins ? plugins.split( ',' ) : [];
  43. // Creates a promise for the loading of each plugin and returns a main promise that resolves when all are
  44. // done.
  45. return Promise.all( plugins.map( pluginPromise, this ) )
  46. .then( () => loaded );
  47. // Returns a promise that will load the plugin and add it to the collection before resolving.
  48. function pluginPromise( plugin ) {
  49. return new Promise( ( resolve, reject ) => {
  50. // Do nothing if the plugin is already loaded (or if is being loaded right now).
  51. if ( this.get( plugin ) || loading[ plugin ] ) {
  52. return resolve();
  53. }
  54. CKEDITOR.require( [ 'plugin!' + plugin ],
  55. // Success callback.
  56. ( LoadedPlugin ) => {
  57. const deps = getPluginDeps( plugin );
  58. const isPluginDep = plugin.indexOf( '/' ) > 0;
  59. let loadedPlugin;
  60. if ( !isPluginDep ) {
  61. loadedPlugin = new LoadedPlugin( this._editor );
  62. if ( !( loadedPlugin instanceof Plugin ) ) {
  63. /**
  64. * The plugin is not an instance of Plugin.
  65. *
  66. * @error plugincollection-instance
  67. * @param {String} plugin The name of the plugin that is not an instance of Plugin.
  68. */
  69. return reject(
  70. new CKEditorError(
  71. 'plugincollection-instance: The plugin is not an instance of Plugin.',
  72. { plugin: plugin }
  73. )
  74. );
  75. }
  76. loadedPlugin.name = plugin;
  77. loadedPlugin.path = CKEDITOR.getPluginPath( plugin );
  78. loadedPlugin.deps = deps;
  79. }
  80. loading[ plugin ] = true;
  81. // Resolve with a promise that resolves once all dependencies are loaded.
  82. resolve(
  83. Promise.all( deps.map( pluginPromise, this ) )
  84. .then( () => {
  85. // Once dependencies are loaded, add the new instance of the loaded plugin to
  86. // the collection. This guarantees that dependecies come first in the collection.
  87. if ( !isPluginDep ) {
  88. this.add( loadedPlugin );
  89. loaded.push( loadedPlugin );
  90. }
  91. } )
  92. );
  93. },
  94. // Error callback.
  95. ( err ) => {
  96. /**
  97. * It was not possible to load the plugin.
  98. *
  99. * @error plugincollection-load
  100. * @param {String} plugin The name of the plugin that could not be loaded.
  101. */
  102. log.error( 'plugincollection-load: It was not possible to load the plugin.', { plugin: plugin } );
  103. reject( err );
  104. }
  105. );
  106. } );
  107. }
  108. function getPluginDeps( name ) {
  109. // Get the list of AMD modules that the plugin depends on.
  110. let deps = CKEDITOR._dependencies[ 'plugin!' + name ] || [];
  111. deps = deps
  112. // Pick only dependencies that are other plugins.
  113. .filter( dep => dep.indexOf( 'plugin!' ) === 0 )
  114. // Remove the 'plugin!' prefix.
  115. .map( dep => dep.substr( 7 ) );
  116. return deps;
  117. }
  118. }
  119. }
  120. return PluginCollection;
  121. } );