module__amd.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /* globals bender, define, require */
  6. 'use strict';
  7. /**
  8. * AMD tools related to CKEditor.
  9. */
  10. const utils = {
  11. /**
  12. * Helper for generating a full module path from a simplified name (similar to simplified plugin naming convention).
  13. *
  14. * Transforms:
  15. *
  16. * * `foo` -> `/ckeditor5/foo/foo.js`
  17. * * `foo/bar` -> `/ckeditor5/foo/bar.js`
  18. *
  19. * If the path is already absolute, then it will be returned without any changes.
  20. *
  21. * @param {String} modulePath The simplified path.
  22. * @returns {String} The real path.
  23. */
  24. getModulePath( modulePath ) {
  25. // Do nothing – path is already absolute.
  26. if ( modulePath.startsWith( '/' ) ) {
  27. return modulePath;
  28. }
  29. if ( modulePath.indexOf( '/' ) < 0 ) {
  30. modulePath = modulePath + '/' + modulePath;
  31. }
  32. return '/ckeditor5/' + modulePath + '.js';
  33. },
  34. /**
  35. * Shorthand for defining an AMD module.
  36. *
  37. * This method uses {@link #getModulePath} to process module and dependency paths so you need to use
  38. * the simplified notation.
  39. *
  40. * For simplicity the dependencies passed to the `body` will be unwrapped
  41. * from the ES6 module object (so only the default export will be available). Also the returned value
  42. * will be automatically handled as a default export.
  43. *
  44. * If you need to define a module which has access to other exports or can export more values,
  45. * use the global `define()` function:
  46. *
  47. * define( 'my/module', [ 'exports', 'foo', ... ], ( FooModule, ... ) {
  48. * const FooClass = FooModule.default;
  49. * const FooOtherProp = FooModule.otherProp;
  50. *
  51. * exports.default = MyClass;
  52. * exports.otherProp = 1;
  53. * } );
  54. *
  55. * **Note:** Since this method automatically unwraps modules from the ES6 module object when passing them
  56. * to the `body` function, circular dependencies will not work. If you need them, either use the raw `define()`
  57. * as shown above, or keep all the definitions outside modules and only access the variables from the scope:
  58. *
  59. * PluginE = createPlugin( 'E' );
  60. * PluginF = createPlugin( 'F' );
  61. *
  62. * PluginF.requires = [ PluginE ];
  63. * PluginE.requires = [ PluginF ];
  64. *
  65. * amdTestUtils.define( 'E', [ 'core/plugin', 'F' ], () => {
  66. * return PluginE;
  67. * } );
  68. *
  69. * amdTestUtils.define( 'E', [ 'core/plugin', 'E' ], () => {
  70. * return PluginF;
  71. * } );
  72. *
  73. * @param {String} path Path to the module.
  74. * @param {String[]} deps Dependencies of the module.
  75. * @param {Function} body Module body.
  76. */
  77. define( path, deps, body ) {
  78. if ( arguments.length == 2 ) {
  79. body = deps;
  80. deps = [];
  81. }
  82. deps = deps.map( utils.getModulePath );
  83. // Use the exports object instead of returning from modules in order to handle circular deps.
  84. // http://requirejs.org/docs/api.html#circular
  85. deps.unshift( 'exports' );
  86. define( utils.getModulePath( path ), deps, function( exports ) {
  87. const loadedDeps = Array.from( arguments ).slice( 1 ).map( ( module ) => module.default );
  88. exports.default = body.apply( this, loadedDeps );
  89. } );
  90. },
  91. /**
  92. * Gets an object which holds the CKEditor modules guaranteed to be loaded before tests start.
  93. *
  94. * This method uses {@link #getModulePath} to process module and dependency paths so you need to use
  95. * the simplified notation.
  96. *
  97. * const modules = amdTestUtils.require( { editor: 'core/Editor' } );
  98. *
  99. * // Later on, inside tests:
  100. * const Editor = modules.editor;
  101. *
  102. * @params {Object} modules The object (`ref => modulePath`) with modules to be loaded.
  103. * @returns {Object} The object that will hold the loaded modules.
  104. */
  105. require( modules ) {
  106. const resolved = {};
  107. const paths = [];
  108. const names = [];
  109. const done = bender.defer();
  110. for ( let name in modules ) {
  111. names.push( name );
  112. paths.push( utils.getModulePath( modules[ name ] ) );
  113. }
  114. require( paths, function( ...loaded ) {
  115. for ( let i = 0; i < names.length; i++ ) {
  116. resolved[ names[ i ] ] = loaded[ i ].default;
  117. }
  118. // Finally give green light for tests to start.
  119. done();
  120. } );
  121. return resolved;
  122. }
  123. };
  124. export default utils;