ソースを参照

Started porting modules to ES6.

Piotrek Koszuliński 10 年 前
コミット
92943ce602

+ 1 - 5
.jshintrc

@@ -11,9 +11,5 @@
 	"strict": true,
 	"varstmt": true,
 
-	"globalstrict": true,
-
-	"globals": {
-		"CKEDITOR": false
-	}
+	"globalstrict": true
 }

+ 3 - 16
bender.js

@@ -2,9 +2,6 @@
 
 'use strict';
 
-// Set it to true to test with the build version.
-const isBuild = false;
-
 const config = {
 	plugins: [
 		'benderjs-chai',
@@ -21,9 +18,9 @@ const config = {
 		'ckeditor': {
 			path: '.',
 			files: [
-				'node_modules/requirejs/require.js',
-				'ckeditor.js'
-			]
+				'node_modules/requirejs/require.js'
+			],
+			basePath: '/apps/ckeditor/dist/amd/'
 		}
 	},
 
@@ -48,14 +45,4 @@ const config = {
 	}
 };
 
-if ( isBuild ) {
-	// Change the 'ckeditor' application to point to the build.
-	config.applications.ckeditor = {
-		path: 'build',
-		files: [
-			'ckeditor.js'
-		]
-	};
-}
-
 module.exports = config;

+ 73 - 116
ckeditor.js

@@ -3,131 +3,88 @@
  * For licensing, see LICENSE.md.
  */
 
-/* global requirejs, define, require */
-
 'use strict';
 
 // This file is shared by the dev and release versions of CKEditor. It bootstraps the API.
 
-( function( root ) {
-	const CKEDITOR = root.CKEDITOR = {
-		/**
-		 * Computes the value of the `basePath` property.
-		 *
-		 * @private
-		 * @method
-		 * @returns {String} A full URL.
-		 */
-		_getBasePath: getBasePath,
-
-		/**
-		 * The list of dependencies of **named** AMD modules created with `CKEDITOR.define`. This is mainly used to
-		 * trace the dependency tree of plugins.
-		 */
-		_dependencies: {},
-
-		/**
-		 * The full URL for the CKEditor installation directory.
-		 *
-		 * It is possible to manually provide the base path by setting a global variable named `CKEDITOR_BASEPATH`. This
-		 * global variable must be set **before** the editor script loading.
-		 *
-		 *		console.log( CKEDITOR.basePath ); // e.g. 'http://www.example.com/ckeditor/'
-		 *
-		 * @property {String}
-		 */
-		basePath: getBasePath(),
-
-		/**
-		 * Whether the app should work in the "debug mode" (aka "verbose mode").
-		 *
-		 * You can use the `CKEDITOR.isDebug` condition in order to wrap code that should be removed in the build version:
-		 *
-		 *		if ( CKEDITOR.isDebug ) {
-		 *			if ( doSomeSuperUnnecessaryDebugChecks() ) {
-		 *				throw new CKEditorError( 'sth-broke: Kaboom!' );
-		 *			}
-		 *		}
-		 *
-		 * See also {@link #isDev}.
-		 *
-		 * @property
-		 */
-		isDebug: true,
-
-		/**
-		 * Defines an AMD module.
-		 *
-		 * See https://github.com/ckeditor/ckeditor5-design/wiki/AMD for more details about our AMD API.
-		 *
-		 * @method
-		 * @member CKEDITOR
-		 */
-		define( name, deps ) {
-			// If this is a named module with dependencies, save this in the dependency list.
-			if ( Array.isArray( deps ) && name && !this._dependencies[ name ] ) {
-				this._dependencies[ name ] = deps;
-			}
-
-			return define.apply( this, arguments );
-		},
+import CKEDITOR_CORE from './ckeditor5-core/ckeditor.js';
+import utilsObject from './ckeditor5-core/lib/lodash/object.js';
+
+const CKEDITOR = {
+	/**
+	 * The full URL for the CKEditor installation directory.
+	 *
+	 * It is possible to manually provide the base path by setting a global variable named `CKEDITOR_BASEPATH`. This
+	 * global variable must be set **before** the editor script loading.
+	 *
+	 *		console.log( CKEDITOR.basePath ); // e.g. 'http://www.example.com/ckeditor/'
+	 *
+	 * @readonly
+	 * @property {String}
+	 */
+	basePath: getBasePath(),
+
+	/**
+	 * Whether the app should work in the "debug mode" (aka "verbose mode").
+	 *
+	 * You can use the `CKEDITOR.isDebug` condition in order to wrap code that should be removed in the build version:
+	 *
+	 *		if ( CKEDITOR.isDebug ) {
+	 *			if ( doSomeSuperUnnecessaryDebugChecks() ) {
+	 *				throw new CKEditorError( 'sth-broke: Kaboom!' );
+	 *			}
+	 *		}
+	 *
+	 * See also {@link #isDev}.
+	 *
+	 * @readonly
+	 */
+	isDebug: true,
+
+	/**
+	 * A flag specifying whether CKEditor is running in development mode (original source code).
+	 *
+	 * This property is not defined in production (compiled, build code).
+	 *
+	 * See also {@link #isDebug}.
+	 *
+	 * @readonly
+	 */
+	isDev: true,
+
+	/**
+	 * Computes the value of the `basePath` property.
+	 *
+	 * @private
+	 * @method
+	 * @returns {String} A full URL.
+	 */
+	_getBasePath: getBasePath
+};
+
+utilsObject.extend( CKEDITOR, CKEDITOR_CORE );
+
+function getBasePath() {
+	if ( window.CKEDITOR_BASEPATH ) {
+		return window.CKEDITOR_BASEPATH;
+	}
 
-		/**
-		 * Retrieves one or more AMD modules.
-		 *
-		 * Note that the CKEditor AMD API does not download modules on demand so be sure to have their relative scripts
-		 * available in the page.
-		 *
-		 * See https://github.com/ckeditor/ckeditor5-design/wiki/AMD for more details about our AMD API.
-		 *
-		 * @method
-		 * @member CKEDITOR
-		 */
-		require: require
-	};
+	const scripts = document.getElementsByTagName( 'script' );
+	const basePathSrcPattern = /(^|.*[\\\/])ckeditor\.js(?:\?.*|;.*)?$/i;
+	let path;
 
-	requirejs.config( {
-		// Modules are generally relative to the core project.
-		baseUrl: CKEDITOR.basePath + 'node_modules/ckeditor5-core/src/',
+	// Find the first script that src matches ckeditor.js.
+	Array.from( scripts ).some( ( script ) => {
+		const match = script.src.match( basePathSrcPattern );
 
-		// These configurations will make no difference in the build version because the following paths will be
-		// already defined there.
-		paths: {
-			// Hide the core "ckeditor" under a different name.
-			'ckeditor-core': CKEDITOR.basePath + 'node_modules/ckeditor5-core/src/ckeditor',
+		if ( match ) {
+			path = match[ 1 ];
 
-			// The dev version overrides for the "ckeditor" module. This is empty on release.
-			'ckeditor-dev': CKEDITOR.basePath + 'src/ckeditor-dev'
+			return true;
 		}
 	} );
 
-	// Define a new "ckeditor" module, which overrides the core one with the above and the dev stuff.
-	define( 'ckeditor', [ 'ckeditor-core', 'ckeditor-dev', 'utils' ], ( core, dev, utils ) => {
-		root.CKEDITOR = utils.extend( {}, core, root.CKEDITOR, ( dev || /* istanbul ignore next */ {} ) );
-
-		return root.CKEDITOR;
-	} );
-
-	function getBasePath() {
-		if ( window.CKEDITOR_BASEPATH ) {
-			return window.CKEDITOR_BASEPATH;
-		}
-
-		const scripts = document.getElementsByTagName( 'script' );
-		const basePathSrcPattern = /(^|.*[\\\/])ckeditor\.js(?:\?.*|;.*)?$/i;
-		let path;
+	return path;
+}
 
-		// Find the first script that src matches ckeditor.js.
-		[].some.call( scripts, ( script ) => {
-			const match = script.src.match( basePathSrcPattern );
-
-			if ( match ) {
-				path = match[ 1 ];
-
-				return true;
-			}
-		} );
-
-		return path;
-	}
-} )( window );
+export default CKEDITOR;

+ 10 - 5
dev/bender/plugins/ckeditor5/lib/index.js

@@ -18,12 +18,17 @@ module.exports = {
 		this.plugins.addFiles( files );
 
 		this.on( 'test:created', ( test ) => {
+			const moduleRegExp = /node_modules\/ckeditor5-([^\/]+)/;
 			let name = test.displayName;
-
-			name = name.replace( /node_modules\/ckeditor5-core/, 'core: ' );
-			name = name.replace( /node_modules\/ckeditor5-plugin-([^\/]+)/, 'plugin!$1: ' );
-
-			test.displayName = name;
+			let module = name.match( moduleRegExp );
+
+			if ( module ) {
+				test.tags.unshift( 'module!' + module[ 1 ] );
+				test.displayName = name.replace( moduleRegExp, '$1: ' );
+			} else {
+				test.tags.unshift( 'module!ckeditor5' );
+				test.displayName = 'ckeditor5: ' + test.displayName;
+			}
 		} );
 
 		// Add this plugins' scripts before the includes pagebuilder (which handles bender-include directives), so

+ 18 - 17
dev/bender/plugins/ckeditor5/static/extensions.js

@@ -4,16 +4,12 @@
  */
 
 /* jshint node: false, browser: true, globalstrict: true */
-/* globals bender, CKEDITOR */
+/* globals bender, require */
 
 'use strict';
 
 ( () => {
-	// Make Bender wait to start running tests.
-	const done = bender.defer();
-
-	// Wait for the "ckeditor" module to be ready to start testing.
-	CKEDITOR.require( [ 'ckeditor' ], done );
+	const basePath = bender.config.applications.ckeditor.basePath;
 
 	/**
 	 * AMD tools related to CKEditor.
@@ -29,19 +25,24 @@
 			const modules = {};
 			const done = bender.defer();
 
-			const names = [].slice.call( arguments );
+			const names = Array.from( arguments );
+			const modulePaths = names.map( ( name ) => {
+				// Add the prefix to shortened paths like `core/editor` (will be `ckeditor5-core/editor`).
+				// Don't add the prefix to the main file and files frok ckeditor5/ module.
+				if ( name != 'ckeditor' && !( /^ckeditor5\//.test( name ) ) ) {
+					name = 'ckeditor5-' + name;
+				}
+
+				return basePath + name + '.js';
+			} );
 
-			// To avoid race conditions with required modules, require `ckeditor` first and then others. This guarantees
-			// that `ckeditor` will be loaded before any other module.
-			CKEDITOR.require( [ 'ckeditor' ], function() {
-				CKEDITOR.require( names, function() {
-					for ( let i = 0; i < names.length; i++ ) {
-						modules[ names[ i ] ] = arguments[ i ] ;
-					}
+			require( modulePaths, function() {
+				for ( let i = 0; i < names.length; i++ ) {
+					modules[ names[ i ] ] = arguments[ i ].default;
+				}
 
-					// Finally give green light for tests to start.
-					done();
-				} );
+				// Finally give green light for tests to start.
+				done();
 			} );
 
 			return modules;

+ 3 - 1
dev/tasks/gulp/build.js

@@ -81,7 +81,9 @@ module.exports = ( config ) => {
 			 * @returns {Stream}
 			 */
 			modules( watch ) {
-				const modulePathPattern = new RegExp( `node_modules${ sep }(ckeditor5-[^${ sep }]+)${ sep }src` );
+				// For an odd reason file.dirname does not contain `node_modules/`. Maybe the base dir
+				// is automatically set to only the varying piece of the path.
+				const modulePathPattern = new RegExp( `(ckeditor5-[^${ sep }]+)${ sep }src` );
 
 				return utils.src( config.ROOT_DIR, 'node_modules/ckeditor5-*/src/**/*.js', watch )
 					.pipe( utils.unpackModules( modulePathPattern ) );

+ 26 - 7
dev/tasks/gulp/utils.js

@@ -71,7 +71,12 @@ const utils = {
 			// Not used so far, but we'll need it.
 			// .pipe( utils.pickVersionedFile( format ) )
 			.pipe( babel( {
-				plugins: [ `transform-es2015-modules-${ babelModuleTranspiler }` ]
+				plugins: [ `transform-es2015-modules-${ babelModuleTranspiler }` ],
+				// Ensure that all paths ends with '.js' because Require.JS (unlike Common.JS/System.JS)
+				// will not add it to module names which look like paths.
+				resolveModuleSource: ( source ) => {
+					return utils.appendModuleExtension( source );
+				}
 			} ) );
 	},
 
@@ -124,12 +129,12 @@ const utils = {
 	 * @returns {Stream}
 	 */
 	unpackModules( modulePathPattern ) {
-		return rename( ( filePath ) => {
-			filePath.dirname = filePath.dirname.replace( modulePathPattern, `${ sep }$1${ sep }` );
+		return rename( ( file ) => {
+			file.dirname = file.dirname.replace( modulePathPattern, `${ sep }$1${ sep }` );
 
 			// Remove now empty src/ dirs.
-			if ( !filePath.extname && filePath.basename == 'src' ) {
-				filePath.basename = '';
+			if ( !file.extname && file.basename == 'src' ) {
+				file.basename = '';
 			}
 		} );
 	},
@@ -140,9 +145,23 @@ const utils = {
 	 * @returns {Stream}
 	 */
 	wrapCKEditor5Module() {
-		return rename( ( filePath ) => {
-			filePath.dirname = path.join( filePath.dirname, 'ckeditor5' );
+		return rename( ( file ) => {
+			file.dirname = path.join( file.dirname, 'ckeditor5' );
 		} );
+	},
+
+	/**
+	 * Appends file extension to file URLs. Tries to not touch named modules.
+	 *
+	 * @param {String} source
+	 * @returns {String}
+	 */
+	appendModuleExtension( source ) {
+		if ( /^https?:|\.[\/\\]/.test( source ) && !/\.js$/.test( source ) ) {
+			return source + '.js';
+		}
+
+		return source;
 	}
 };
 

+ 1 - 2
package.json

@@ -45,7 +45,6 @@
     "multipipe": "^0.2.1",
     "ncp": "^2.0.0",
     "replace": "^0.3.0",
-    "run-sequence": "^1.1.5",
     "shelljs": "^0",
     "sinon": "^1.17.0"
   },
@@ -61,4 +60,4 @@
     "test": "mocha dev/tests",
     "coverage": "istanbul cover _mocha dev/tests/"
   }
-}
+}

+ 0 - 40
src/ckeditor-dev.js

@@ -1,40 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* global define, requirejs, CKEDITOR */
-
-'use strict';
-
-define( 'ckeditor-dev', () => {
-	return {
-		/**
-		 * A flag specifying whether CKEditor is running in development mode (original source code).
-		 *
-		 * This property is not defined in production (compiled, build code).
-		 *
-		 * See also {@link #isDebug}.
-		 *
-		 * @member CKEDITOR
-		 */
-		isDev: true,
-
-		// Documented in ckeditor5-core/ckeditor.
-		getPluginPath( name ) {
-			return this.basePath + 'node_modules/ckeditor-plugin-' + name + '/src/';
-		}
-	};
-} );
-
-// For the dev version, we override the "plugin" module.
-requirejs.config( {
-	paths: {
-		// The RequireJS "plugin" plugin.
-		'plugin': CKEDITOR.basePath + 'src/plugin',
-
-		// Due to name conflict with the above, we have to save a reference to the core "plugin" module.
-		// See src/plugin.js for more details.
-		'plugin-core': CKEDITOR.basePath + 'node_modules/ckeditor5-core/src/plugin'
-	}
-} );

+ 0 - 40
src/plugin.js

@@ -1,40 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* global define */
-
-'use strict';
-
-// Plugin for RequireJS to properly load CKEditor plugins through the "plugin!name" scheme:
-// "plugin!name" => "node_modules/ckeditor5-plugin-name/name"
-//
-// Due to name conflict with the "ckeditor5-core/plugin" module, a workaround was needed. In this case, we extend the
-// core Plugin class with the necessary RequireJS plugin methods. This should have no harm on the use of the Plugin
-// class.
-
-define( 'plugin', [ 'plugin-core' ], ( CorePlugin ) => {
-	// Called when a "plugin!" module is to be loaded.
-	// http://requirejs.org/docs/plugins.html#apiload
-	CorePlugin.load = function( name, require, onload ) {
-		// We may have a path to plugin modules (e.g. test/somemodule). Here we break the path on slashes.
-		let path = name.split( '/' );
-
-		// Inject the /src/ part right after the plugin name (e.g test/src).
-		path.splice( 1, 0, 'src' );
-
-		// If we didn't have any subpart in the path, inject the plugin name at the end (e.g. test/src/test).
-		if ( path.length == 2 ) {
-			path.push( path[ 0 ] );
-		}
-
-		// Finally point to the right place, relatively to the `ckeditor5-core/src` directory (in node_modules).
-		path = '../../ckeditor5-plugin-' + path.join( '/' );
-
-		// Now require the module again, using the fully resolved path.
-		require( [ path ], onload, onload.error );
-	};
-
-	return CorePlugin;
-} );

+ 0 - 28
tests/amd/amd.js

@@ -1,28 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-CKEDITOR.define( 'testModule', [ 'ckeditor' ], ( ckeditor ) => {
-	return {
-		test: ( ckeditor && ( typeof ckeditor == 'object' ) )
-	};
-} );
-
-describe( 'CKEDITOR.require()', () => {
-	it( 'should work with a defined module', ( done ) => {
-		CKEDITOR.require( [ 'testModule' ], ( testModule ) => {
-			expect( testModule ).to.have.property( 'test' ).to.be.true();
-			done();
-		} );
-	} );
-
-	it( 'should work with a core module', ( done ) => {
-		CKEDITOR.require( [ 'utils' ], ( utils ) => {
-			expect( utils ).to.be.an( 'object' );
-			done();
-		} );
-	} );
-} );

+ 1 - 35
tests/ckeditor/ckeditor.js

@@ -5,41 +5,7 @@
 
 'use strict';
 
-const modules = bender.amd.require( 'ckeditor', 'ckeditor-core' );
-
-describe( 'getPluginPath()', () => {
-	it( 'should return a proper path', () => {
-		const CKEDITOR = modules.ckeditor;
-
-		const basePath = CKEDITOR.basePath;
-		const path = CKEDITOR.getPluginPath( 'test' );
-
-		if ( CKEDITOR.isDev ) {
-			expect( path ).to.equal( basePath + 'node_modules/ckeditor-plugin-test/src/' );
-		} else {
-			expect( path ).to.equal( basePath + 'plugins/test/' );
-		}
-	} );
-
-	it( '(the production version) should work even when in dev', () => {
-		const CKEDITOR = modules.ckeditor;
-		const core = modules[ 'ckeditor-core' ];
-
-		// To be able to run this test on both dev and production code, we need to override getPluginPath with the
-		// core version of it and restore it after testing.
-		const originalGetPluginPath = CKEDITOR.getPluginPath;
-		CKEDITOR.getPluginPath = core.getPluginPath;
-
-		// This test is good for both the development and production codes.
-		const basePath = CKEDITOR.basePath;
-		const path = CKEDITOR.getPluginPath( 'test' );
-
-		// Revert the override before assertions or it will not do it in case of errors.
-		CKEDITOR.getPluginPath = originalGetPluginPath;
-
-		expect( path ).to.equal( basePath + 'plugins/test/' );
-	} );
-} );
+const modules = bender.amd.require( 'ckeditor' );
 
 describe( 'isDebug', () => {
 	it( 'is a boolean', () => {

+ 0 - 31
tests/plugin/plugin.js

@@ -1,31 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-describe( 'CKEDITOR.require()', () => {
-	it( 'should load a CKEditor plugin', ( done ) => {
-		CKEDITOR.require( [ 'plugin!devtest' ], ( DevTest ) => {
-			expect( DevTest ).to.have.property( 'isDevTest' );
-			done();
-		} );
-	} );
-
-	it( 'should load dependencies on CKEditor plugins', ( done ) => {
-		CKEDITOR.require( [ 'plugin!devtest/someclass' ], ( SomeClass ) => {
-			expect( SomeClass ).to.have.property( 'isSomeClass' );
-			done();
-		} );
-	} );
-
-	it( 'should load a dependency into a CKEditor plugin', ( done ) => {
-		CKEDITOR.require( [ 'plugin!devtest', 'plugin!devtest/someclass' ], ( DevTest, SomeClass ) => {
-			const test = new DevTest();
-
-			expect( test ).to.have.property( 'someProperty' ).to.be.an.instanceof( SomeClass );
-			done();
-		} );
-	} );
-} );