浏览代码

Merge pull request #261 from ckeditor/t/252

Moved utils to `ckeditor5-dev-utils` package
Szymon Kupś 9 年之前
父节点
当前提交
86cc4f0159

+ 32 - 28
dev/tasks/build/tasks.js

@@ -13,15 +13,14 @@ const gulpWatch = require( 'gulp-watch' );
 const gulpPlumber = require( 'gulp-plumber' );
 const gutil = require( 'gulp-util' );
 const filter = require( 'gulp-filter' );
-const utils = require( './utils' );
 const runSequence = require( 'run-sequence' );
-const tools = require( '../../utils/tools' );
+const { build, tools } = require( 'ckeditor5-dev-utils' );
 
 module.exports = ( config ) => {
 	const buildDir = path.join( config.ROOT_DIR, config.BUILD_DIR );
 	const themesGlob = path.join( 'theme', '**', '*.scss' );
 	const iconsGlob = path.join( 'theme', 'icons', '*.svg' );
-	const args = utils.parseArguments();
+	const args = build.parseArguments();
 
 	const tasks = {
 		clean: {
@@ -42,7 +41,7 @@ module.exports = ( config ) => {
 			 */
 			js( options ) {
 				// TODO: ES6 default function parameters
-				options = options || utils.parseArguments();
+				options = options || build.parseArguments();
 
 				return tools.clean( buildDir, path.join( `@(${ options.formats.join( '|' ) })`, '!(theme)' ) );
 			},
@@ -77,7 +76,7 @@ module.exports = ( config ) => {
 					const glob = path.join( config.ROOT_DIR, 'ckeditor.js' );
 
 					return gulp.src( glob )
-						.pipe( watch ? gulpWatch( glob ) : utils.noop() );
+						.pipe( watch ? gulpWatch( glob ) : build.noop() );
 				},
 
 				/**
@@ -90,8 +89,8 @@ module.exports = ( config ) => {
 					const glob = path.join( config.ROOT_DIR, '@(src|tests)', '**', '*' );
 
 					return gulp.src( glob, { nodir: true } )
-						.pipe( watch ? gulpWatch( glob ) : utils.noop() )
-						.pipe( utils.renameCKEditor5Files() );
+						.pipe( watch ? gulpWatch( glob ) : build.noop() )
+						.pipe( build.renameCKEditor5Files() );
 				},
 
 				/**
@@ -101,7 +100,7 @@ module.exports = ( config ) => {
 				 * @returns {Stream}
 				 */
 				packages( watch ) {
-					const dirs = utils.getPackages( config.ROOT_DIR );
+					const dirs = build.getPackages( config.ROOT_DIR );
 
 					const streams = dirs.map( ( dirPath ) => {
 						const glob = path.join( dirPath, '@(src|tests)', '**', '*' );
@@ -110,11 +109,11 @@ module.exports = ( config ) => {
 						const opts = { base: baseDir, nodir: true };
 
 						return gulp.src( glob, opts )
-							.pipe( watch ? gulpWatch( glob, opts ) : utils.noop() );
+							.pipe( watch ? gulpWatch( glob, opts ) : build.noop() );
 					} );
 
 					return merge.apply( null, streams )
-						.pipe( utils.renamePackageFiles() );
+						.pipe( build.renamePackageFiles() );
 				}
 			},
 
@@ -124,7 +123,7 @@ module.exports = ( config ) => {
 			 * @returns {Stream}
 			 */
 			sass() {
-				const dirs = utils.getPackages( config.ROOT_DIR );
+				const dirs = build.getPackages( config.ROOT_DIR );
 
 				const streams = dirs.map( ( dirPath ) => {
 					const glob = path.join( dirPath, themesGlob );
@@ -138,7 +137,7 @@ module.exports = ( config ) => {
 			},
 
 			icons() {
-				const dirs = utils.getPackages( config.ROOT_DIR );
+				const dirs = build.getPackages( config.ROOT_DIR );
 
 				const streams = dirs.map( ( dirPath ) => {
 					const glob = path.join( dirPath, iconsGlob );
@@ -196,12 +195,12 @@ module.exports = ( config ) => {
 				// Multipipe and gulp-mirror seem to work this way, so we get a single error emitter.
 				const codeStream = tasks.src.js.all( options.watch )
 					.pipe(
-						utils.noop( ( file ) => {
+						build.noop( ( file ) => {
 							gutil.log( `Processing '${ gutil.colors.cyan( file.path ) }'...` );
 						} )
 					);
-				const conversionStreamGenerator = utils.getConversionStreamGenerator( buildDir );
-				const outputStream = utils.noop();
+				const conversionStreamGenerator = build.getConversionStreamGenerator( buildDir );
+				const outputStream = build.noop();
 
 				let inputStream;
 				let conversionStream;
@@ -237,7 +236,7 @@ module.exports = ( config ) => {
 				}
 
 				function startStreams() {
-					inputStream = utils.noop();
+					inputStream = build.noop();
 					conversionStream = createConversionStream();
 
 					codeStream
@@ -266,7 +265,7 @@ module.exports = ( config ) => {
 					const glob = path.join( config.ROOT_DIR, 'node_modules', 'ckeditor5-*', themesGlob );
 
 					// Initial build.
-					build();
+					buildSass();
 
 					gutil.log( `Watching theme files in '${ gutil.colors.cyan( glob ) }' for changes...` );
 
@@ -274,24 +273,24 @@ module.exports = ( config ) => {
 						gutil.log( `Theme file '${ gutil.colors.cyan( event.path ) }' has been ${ event.type }...` );
 
 						// Re-build the entire theme if the file has been changed.
-						return build();
+						return buildSass();
 					} );
 				} else {
-					return build();
+					return buildSass();
 				}
 
-				function build() {
-					const formatStreams = utils.getThemeFormatDestStreams( buildDir, options.formats );
+				function buildSass() {
+					const formatStreams = build.getThemeFormatDestStreams( buildDir, options.formats );
 
 					return tasks.src.sass()
 						.pipe( gulpPlumber() )
-						.pipe( utils.filterThemeEntryPoints() )
+						.pipe( build.filterThemeEntryPoints() )
 						.pipe(
-							utils.noop( file => {
+							build.noop( file => {
 								gutil.log( `Found theme entry point '${ gutil.colors.cyan( file.path ) }'.` );
 							} )
 						)
-						.pipe( utils.compileThemes( 'ckeditor.css' ) )
+						.pipe( build.compileThemes( 'ckeditor.css' ) )
 						.pipe( mirror( formatStreams ) )
 						.on( 'error', console.log );
 				}
@@ -306,16 +305,21 @@ module.exports = ( config ) => {
 			 * @returns {Stream}
 			 */
 			icons( options ) {
-				const formatStreams = utils.getThemeFormatDestStreams( buildDir, options.formats, format => {
+				const formatStreams = build.getThemeFormatDestStreams( buildDir, options.formats, format => {
 					if ( format !== 'esnext' ) {
-						return utils.transpile( format, utils.getBabelOptionsForSource( format ) );
+						return build.transpile( format, build.getBabelOptionsForSource( format ) );
 					} else {
-						return utils.noop();
+						return build.noop();
 					}
 				} );
 
+				const spriteOptions = {
+					template: path.join( __dirname, 'iconmanagermodel.tpl' ),
+					dest: 'iconmanagermodel.js',
+				};
+
 				return tasks.src.icons()
-					.pipe( utils.compileIconSprite() )
+					.pipe( build.compileIconSprite( spriteOptions ) )
 					.pipe( filter( '*.js' ) )
 					.pipe( mirror( formatStreams ) );
 			}

+ 0 - 612
dev/tasks/build/utils.js

@@ -1,612 +0,0 @@
-/**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-const path = require( 'path' );
-const gulp = require( 'gulp' );
-const rename = require( 'gulp-rename' );
-const replace = require( 'gulp-replace' );
-const gulpBabel = require( 'gulp-babel' );
-const gutil = require( 'gulp-util' );
-const gulpFilter = require( 'gulp-filter' );
-const multipipe = require( 'multipipe' );
-const PassThrough = require( 'stream' ).PassThrough;
-const through = require( 'through2' );
-const fs = require( 'fs' );
-const sass = require( 'node-sass' );
-const minimist = require( 'minimist' );
-const sprite = require( 'gulp-svg-sprite' );
-
-const utils = {
-	/**
-	 * Code which can be appended to a transpiled (into AMD) test files in order to
-	 * load the 'tests' module and defer launching Bender until it's ready.
-	 *
-	 * Note: This code will not be transpiled so keep it in ES5.
-	 */
-	benderLauncherCode:
-`
-require( [ 'tests' ], bender.defer(), function( err ) {
-	// The problem with Require.JS is that there are no stacktraces if we won't log this.
-	console.error( err );
-	console.log( err.stack );
-} );
-`,
-
-	/**
-	 * Module formats supported by the builder.
-	 */
-	SUPPORTED_FORMATS: [ 'esnext', 'amd', 'cjs' ],
-
-	/**
-	 * Creates a simple duplex stream.
-	 *
-	 * @param {Function} [callback] A callback which will be executed with each chunk.
-	 * @returns {Stream}
-	 */
-	noop( callback ) {
-		if ( !callback ) {
-			return new PassThrough( { objectMode: true } );
-		}
-
-		return through( { objectMode: true }, ( file, encoding, throughCallback ) => {
-			callback( file );
-
-			throughCallback( null, file );
-		} );
-	},
-
-	/**
-	 * Saves the files piped into this stream to the `build/` directory.
-	 *
-	 * @param {String} buildDir The `build/` directory path.
-	 * @param {String} format The format of the buildribution (`esnext`, `amd`, or `cjs`).
-	 * @returns {Stream}
-	 */
-	destBuild( buildDir, format ) {
-		const destDir = path.join( buildDir, format );
-
-		return gulp.dest( destDir );
-	},
-
-	/**
-	 * Creates a function generating convertion streams.
-	 * Used to generate `formats.reduce()` callback where `formats` is an array of formats that should be generated.
-	 *
-	 * @param {String} buildDir The `build/` directory path.
-	 * @returns {Function}
-	 */
-	getConversionStreamGenerator( buildDir ) {
-		return ( pipes, format ) => {
-			const conversionPipes = [];
-
-			conversionPipes.push( utils.pickVersionedFile( format ) );
-
-			if ( format != 'esnext' ) {
-				// Convert src files.
-				const filterSource = gulpFilter( ( file ) => {
-					return utils.isSourceFile( file ) && utils.isJSFile( file );
-				}, { restore: true } );
-				const transpileSource = utils.transpile( format, utils.getBabelOptionsForSource( format ) );
-				conversionPipes.push(
-					filterSource,
-					transpileSource,
-					utils.fixCoverage(),
-					filterSource.restore
-				);
-
-				// Convert test files.
-				const filterTests = gulpFilter( ( file ) => {
-					return utils.isTestFile( file ) && utils.isJSFile( file );
-				}, { restore: true } );
-				const transpileTests = utils.transpile( format, utils.getBabelOptionsForTests( format ) );
-				conversionPipes.push(
-					filterTests,
-					transpileTests,
-					format === 'amd' ? utils.appendBenderLauncher() : utils.noop(),
-					filterTests.restore
-				);
-			}
-
-			conversionPipes.push(
-				utils.destBuild( buildDir, format ),
-				utils.noop( ( file ) => {
-					gutil.log( `Finished writing '${ gutil.colors.cyan( file.path ) }'` );
-				} )
-			);
-
-			pipes.push( multipipe.apply( null, conversionPipes ) );
-
-			return pipes;
-		};
-	},
-
-	/**
-	 * Transpiles files piped into this stream to the given format (`amd` or `cjs`).
-	 *
-	 * @param {String} format
-	 * @returns {Stream}
-	 */
-	transpile( format, options ) {
-		return gulpBabel( options )
-			.on( 'error', ( err ) => {
-				gutil.log( gutil.colors.red( `Error (Babel:${ format })` ) );
-				gutil.log( gutil.colors.red( err.message ) );
-				console.log( '\n' + err.codeFrame + '\n' );
-			} );
-	},
-
-	/**
-	 * Adds istanbul ignore to the code created by babel.
-	 *
-	 * @returns {Stream}
-	 */
-	fixCoverage() {
-		return replace(
-			'return obj && obj.__esModule ? obj :',
-			'/* istanbul ignore next */\n\t\t' +
-			'return obj && obj.__esModule ? obj :' );
-	},
-
-	/**
-	 * Returns an object with Babel options for the source code.
-	 *
-	 * @param {String} format
-	 * @returns {Object} options
-	 */
-	getBabelOptionsForSource( format ) {
-		return {
-			plugins: utils.getBabelPlugins( format ),
-			// 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: format == 'cjs' ? utils.resolveModuleSource : utils.appendModuleExtension
-		};
-	},
-
-	/**
-	 * Returns an object with Babel options for the test code.
-	 *
-	 * @param {String} format
-	 * @returns {Object} options
-	 */
-	getBabelOptionsForTests( format ) {
-		return {
-			plugins: utils.getBabelPlugins( format ),
-			resolveModuleSource: format == 'cjs' ? utils.resolveModuleSource : utils.appendModuleExtension,
-			moduleIds: true,
-			moduleId: 'tests'
-		};
-	},
-
-	/**
-	 * Returns an array of Babel plugins to use.
-	 *
-	 * @param {String} format
-	 * @returns {Array}
-	 */
-	getBabelPlugins( format ) {
-		const babelModuleTranspilers = {
-			amd: 'amd',
-			cjs: 'commonjs'
-		};
-		const babelModuleTranspiler = babelModuleTranspilers[ format ];
-
-		if ( !babelModuleTranspiler ) {
-			throw new Error( `Incorrect format: ${ format }` );
-		}
-
-		return [
-			// Note: When plugin is specified by its name, Babel loads it from a context of a
-			// currently transpiled file (in our case - e.g. from ckeditor5-core/src/foo.js).
-			// Obviously that fails, since we have all the plugins installed only in ckeditor5/
-			// and we want to have them only there to avoid installing them dozens of times.
-			//
-			// Anyway, I haven't found in the docs that you can also pass a plugin instance here,
-			// but it works... so let's hope it will.
-			require( `babel-plugin-transform-es2015-modules-${ babelModuleTranspiler }` )
-		];
-	},
-
-	/**
-	 * Appends the {@link #benderLauncherCode} at the end of the file.
-	 *
-	 * @returns {Stream}
-	 */
-	appendBenderLauncher() {
-		return through( { objectMode: true }, ( file, encoding, callback ) => {
-			if ( !file.isNull() ) {
-				file.contents = new Buffer( file.contents.toString() + utils.benderLauncherCode );
-			}
-
-			callback( null, file );
-		} );
-	},
-
-	/**
-	 * Allows us to pick one of files suffixed with the format (`__esnext`, `__amd`, or `__cjs`) and removes
-	 * files with other suffixes from the stream.
-	 *
-	 * For example: we have `load__esnext.js`, `load__amd.js` and `load__cjs.js`. After applying this
-	 * transformation when compiling code for a specific format the proper file will be renamed to `load.js`.
-	 * Files not matching a specified format will be removed.
-	 *
-	 * @param {String} format
-	 * @returns {Stream}
-	 */
-	pickVersionedFile( format ) {
-		const rejectedFormats = utils.SUPPORTED_FORMATS
-			.filter( ( item ) => item !== format );
-		const pickRegexp = new RegExp( `__${ format }$` );
-		const rejectRegexp = new RegExp( `__(${ rejectedFormats.join( '|' ) }).js$` );
-
-		const pick = rename( ( path ) => {
-			path.basename = path.basename.replace( pickRegexp, '' );
-		} );
-		const remove = gulpFilter( ( file ) => !rejectRegexp.test( file.path ) );
-
-		return multipipe( pick, remove );
-	},
-
-	/**
-	 * Processes paths of files inside CKEditor5 packages.
-	 *
-	 * * `ckeditor5-xxx/src/foo/bar.js` -> `ckeditor5/xxx/foo/bar.js`
-	 * * `ckeditor5-xxx/tests/foo/bar.js` -> `tests/xxx/foo/bar.js`
-	 *
-	 * @returns {Stream}
-	 */
-	renamePackageFiles() {
-		return rename( ( file ) => {
-			const dirFrags = file.dirname.split( path.sep );
-
-			// Validate the input for the clear conscious.
-
-			if ( dirFrags[ 0 ].indexOf( 'ckeditor5-' ) !== 0 ) {
-				throw new Error( 'Path should start with "ckeditor5-".' );
-			}
-
-			dirFrags[ 0 ] = dirFrags[ 0 ].replace( /^ckeditor5-/, '' );
-
-			const firstFrag = dirFrags[ 1 ];
-
-			if ( firstFrag == 'src' ) {
-				// Remove 'src/'.
-				dirFrags.splice( 1, 1 );
-
-				// Temporary implementation of the UI lib option. See #88.
-				if ( dirFrags[ 0 ] == 'ui-default' ) {
-					dirFrags[ 0 ] = 'ui';
-				}
-
-				// And prepend 'ckeditor5/'.
-				dirFrags.unshift( 'ckeditor5' );
-			} else if ( firstFrag == 'tests' ) {
-				// Remove 'tests/' from the package dir.
-				dirFrags.splice( 1, 1 );
-
-				// And prepend 'tests/'.
-				dirFrags.unshift( 'tests' );
-			} else {
-				throw new Error( 'Path should start with "ckeditor5-*/(src|tests|theme)".' );
-			}
-
-			file.dirname = path.join.apply( null, dirFrags );
-		} );
-	},
-
-	/**
-	 * Processes paths of files inside the main CKEditor5 package.
-	 *
-	 * * `src/foo/bar.js` -> `ckeditor5/foo/bar.js`
-	 * * `tests/foo/bar.js` -> `tests/ckeditor5/foo/bar.js`
-	 *
-	 * @returns {Stream}
-	 */
-	renameCKEditor5Files() {
-		return rename( ( file ) => {
-			const dirFrags = file.dirname.split( path.sep );
-			const firstFrag = dirFrags[ 0 ];
-
-			if ( firstFrag == 'src' ) {
-				// Replace 'src/' with 'ckeditor5/'.
-				// src/path.js -> ckeditor5/path.js
-				dirFrags.splice( 0, 1, 'ckeditor5' );
-			} else if ( firstFrag == 'tests' ) {
-				// Insert 'ckeditor5/' after 'tests/'.
-				// tests/foo.js -> tests/ckeditor5/foo.js
-				dirFrags.splice( 1, 0, 'ckeditor5' );
-			} else {
-				throw new Error( 'Path should start with "src" or "tests".' );
-			}
-
-			file.dirname = path.join.apply( null, dirFrags );
-		} );
-	},
-
-	/**
-	 * 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;
-	},
-
-	/**
-	 * Checks whether a file is a test file.
-	 *
-	 * @param {Vinyl} file
-	 * @returns {Boolean}
-	 */
-	isTestFile( file ) {
-		// TODO this should be based on bender configuration (config.tests.*.paths).
-		if ( !file.relative.startsWith( 'tests' + path.sep ) ) {
-			return false;
-		}
-
-		const dirFrags = file.relative.split( path.sep );
-
-		return !dirFrags.some( dirFrag => {
-			return dirFrag.startsWith( '_' ) && dirFrag != '_utils-tests';
-		} );
-	},
-
-	/**
-	 * Checks whether a file is a source file.
-	 *
-	 * @param {Vinyl} file
-	 * @returns {Boolean}
-	 */
-	isSourceFile( file ) {
-		return !utils.isTestFile( file );
-	},
-
-	/**
-	 * Checks whether a file is a JS file.
-	 *
-	 * @param {Vinyl} file
-	 * @returns {Boolean}
-	 */
-	isJSFile( file ) {
-		return file.path.endsWith( '.js' );
-	},
-
-	/**
-	 * Finds all CKEditor5 package directories in "node_modules" folder.
-	 *
-	 * @param {String} rootDir A root directory containing "node_modules" folder.
-	 * @returns {Array} Array of ckeditor5-* package directory paths.
-	 */
-	getPackages( rootDir ) {
-		// Find all CKEditor5 package directories. Resolve symlinks so we watch real directories
-		// in order to workaround https://github.com/paulmillr/chokidar/issues/419.
-		return fs.readdirSync( path.join( rootDir, 'node_modules' ) )
-			// Look for ckeditor5-* directories.
-			.filter( fileName => {
-				return fileName.indexOf( 'ckeditor5-' ) === 0;
-			} )
-			// Resolve symlinks and keep only directories.
-			.map( fileName => {
-				let filePath = path.join( rootDir, 'node_modules', fileName );
-				let stat = fs.lstatSync( filePath );
-
-				if ( stat.isSymbolicLink() ) {
-					filePath = fs.realpathSync( filePath );
-					stat = fs.lstatSync( filePath );
-				}
-
-				if ( stat.isDirectory() ) {
-					return filePath;
-				}
-
-				// Filter...
-				return false;
-			} )
-			// 					...those out.
-			.filter( filePath => filePath );
-	},
-
-	/**
-	 * Filters theme entry points only from a stream of SCSS files.
-	 *
-	 * @returns {Stream}
-	 */
-	filterThemeEntryPoints() {
-		return gulpFilter( '**/theme.scss' );
-	},
-
-	/**
-	 * Given the input stream of theme entry-point files (theme.scss), this method:
-	 * 	1. Collects paths to entry-point.
-	 * 	2. Builds the output CSS theme file using aggregated entry-points.
-	 * 	3. Returns a stream containing built CSS theme file.
-	 *
-	 * @param {String} fileName The name of the output CSS theme file.
-	 * @returns {Stream}
-	 */
-	compileThemes( fileName ) {
-		const paths = [];
-		const stream = through.obj( collectThemeEntryPoint, renderThemeFromEntryPoints );
-
-		function collectThemeEntryPoint( file, enc, callback ) {
-			paths.push( file.path );
-
-			callback();
-		}
-
-		function renderThemeFromEntryPoints( callback ) {
-			gutil.log( `Compiling '${ gutil.colors.cyan( fileName ) }' from ${ gutil.colors.cyan( paths.length ) } entry points...` );
-
-			// Sort to make sure theme is the very first SASS to build. Otherwise,
-			// packages using mixins and variables from that theme will throw errors
-			// because such are not available at this stage of compilation.
-			const dataToRender = paths.sort( a => -a.indexOf( 'ckeditor5-theme' ) )
-				// Make sure windows\\style\\paths are preserved.
-				.map( p => `@import "${ p.replace( /\\/g, '\\\\' ) }";` )
-				.join( '\n' );
-
-			try {
-				const rendered = sass.renderSync( utils.getSassOptions( dataToRender ) );
-
-				stream.push( new gutil.File( {
-					path: fileName,
-					contents: new Buffer( rendered.css )
-				} ) );
-
-				callback();
-			} catch ( err ) {
-				callback( err );
-			}
-		}
-
-		return stream;
-	},
-
-	/**
-	 * Parses command line arguments and returns them as a user-friendly hash.
-	 *
-	 * @param {String} dataToRender
-	 * @returns {Object}
-	 */
-	getSassOptions( dataToRender ) {
-		return {
-			data: dataToRender,
-			sourceMap: true,
-			sourceMapEmbed: true,
-			outputStyle: 'expanded',
-			sourceComments: true
-		};
-	},
-
-	/**
-	 * Parses command line arguments and returns them as a user-friendly hash.
-	 *
-	 * @returns {Object} options
-	 * @returns {Array} [options.formats] Array of specified output formats ("esnext" or "amd").
-	 * @returns {Boolean} [options.watch] A flag which enables watch mode.
-	 */
-	parseArguments() {
-		const options = minimist( process.argv.slice( 2 ), {
-			string: [
-				'formats'
-			],
-
-			boolean: [
-				'watch'
-			],
-
-			default: {
-				formats: 'amd',
-				watch: false
-			}
-		} );
-
-		options.formats = options.formats.split( ',' );
-
-		return options;
-	},
-
-	/**
-	 * Given a stream of `.svg` files it returns a stream containing JavaScript
-	 * icon sprite file.
-	 *
-	 * @returns {Stream}
-	 */
-	compileIconSprite() {
-		return sprite( utils.getIconSpriteOptions() );
-	},
-
-	/**
-	 * Returns svg-sprite util options to generate <symbol>-based, JavaScript
-	 * sprite file.
-	 *
-	 * @returns {Object}
-	 */
-	getIconSpriteOptions() {
-		return {
-			shape: {
-				id: {
-					// Note: Consider unix/style/paths and windows\\style\\paths.
-					generator: name => `ck-icon-${ name.match( /([^\/\\]*)\.svg$/ )[ 1 ] }`
-				},
-			},
-			svg: {
-				xmlDeclaration: false,
-				doctypeDeclaration: false,
-			},
-			mode: {
-				symbol: {
-					dest: './', // Flatten symbol/ folder.
-					inline: true,
-					render: {
-						js: {
-							template: path.join( __dirname, 'iconmanagermodel.tpl' ),
-							dest: 'iconmanagermodel.js',
-						}
-					}
-				}
-			}
-		};
-	},
-
-	/**
-	 * Given a stream of files it returns an array of gulp-mirror streams outputting
-	 * files to `build/[formats]/theme/` directories for each of desired output formats (cjs, amd, etc.).
-	 *
-	 * @param {String} buildDir A path to /build directory.
-	 * @param {Array} formats An array of desired output formats.
-	 * @param {Function} [transformationStream] A stream used to transform files before they're saved to
-	 * desired `build/[formats]/theme` directories. Useful for transpilation.
-	 * @returns {Stream[]} An array of streams.
-	 */
-	getThemeFormatDestStreams( buildDir, formats, transformationStream ) {
-		return formats.map( f => {
-			return multipipe(
-				transformationStream ? transformationStream( f ) : utils.noop(),
-				gulp.dest( path.join( buildDir, f, 'theme' ) ),
-				utils.noop( file => {
-					gutil.log( `Output for ${ gutil.colors.cyan( f ) } is '${ gutil.colors.cyan( file.path ) }'.` );
-				} )
-			);
-		} );
-	},
-
-	/**
-	 * Resolves CommonJS module source path.
-	 *
-	 * @param {String} source Module path passed to require() method.
-	 * @param {String} file Path to a file where require() method is called.
-	 * @returns {String} Fixed module path.
-	 */
-	resolveModuleSource( source, file ) {
-		// If path is relative - leave it as is.
-		if ( !path.isAbsolute( source ) ) {
-			return source;
-		}
-
-		// Find relative path of test file from cwd directory.
-		let testFile = path.relative( process.cwd(), file );
-
-		// Append `/` as all files uses it as root inside transpiled versions.
-		testFile = path.join( path.sep, testFile );
-
-		// Find relative path from test file to source.
-		let relativePath = path.relative( path.dirname( testFile ), path.dirname( source ) );
-		relativePath = path.join( relativePath, path.basename( source ) );
-
-		// Convert windows path to posix.
-		relativePath = relativePath.replace( /\\/g, '/' );
-
-		return utils.appendModuleExtension( ( relativePath.startsWith( '../' ) ? '' : './' ) + relativePath );
-	}
-};
-
-module.exports = utils;

+ 1 - 1
dev/tasks/bundle/tasks.js

@@ -16,7 +16,7 @@ const utils = require( './utils' );
 const rollup = require( 'rollup' ).rollup;
 const rollupBabel = require( 'rollup-plugin-babel' );
 const mkdirp = require( 'mkdirp' );
-const tools = require( '../../utils/tools' );
+const { tools } = require( 'ckeditor5-dev-utils' );
 
 module.exports = ( config ) => {
 	const args = utils.parseArguments();

+ 1 - 3
dev/tasks/dev/tasks/create-package.js

@@ -6,10 +6,8 @@
 'use strict';
 
 const inquiries = require( '../utils/inquiries' );
-const git = require( '../../../utils/git' );
-const tools = require( '../../../utils/tools' );
 const path = require( 'path' );
-const log = require( '../../../utils/log' );
+const { git, tools, log } = require( 'ckeditor5-dev-utils' );
 
 /**
  * 1. Ask for new package name.

+ 2 - 3
dev/tasks/dev/tasks/init.js

@@ -5,8 +5,7 @@
 
 'use strict';
 
-const ckeditor5Dirs = require( '../../../utils/ckeditor5-dirs' );
-const log = require( '../../../utils/log' );
+const { workspace, log } = require( 'ckeditor5-dev-utils' );
 
 /**
  * 1. Get CKEditor5 dependencies from package.json file.
@@ -19,7 +18,7 @@ const log = require( '../../../utils/log' );
  */
 module.exports = ( installTask, ckeditor5Path, packageJSON, workspaceRoot ) => {
 	// Get all CKEditor dependencies from package.json.
-	const dependencies = ckeditor5Dirs.getDependencies( packageJSON.dependencies );
+	const dependencies = workspace.getDependencies( packageJSON.dependencies );
 
 	if ( dependencies ) {
 		for ( let dependency in dependencies ) {

+ 1 - 3
dev/tasks/dev/tasks/install.js

@@ -5,10 +5,8 @@
 
 'use strict';
 
-const git = require( '../../../utils/git' );
-const tools = require( '../../../utils/tools' );
 const path = require( 'path' );
-const log = require( '../../../utils/log' );
+const { git, tools, log } = require( 'ckeditor5-dev-utils' );
 
 /**
  * This tasks install specified package in development mode. It can be executed by typing:

+ 3 - 5
dev/tasks/dev/tasks/relink.js

@@ -5,10 +5,8 @@
 
 'use strict';
 
-const ckeditor5Dirs = require( '../../../utils/ckeditor5-dirs' );
-const tools = require( '../../../utils/tools' );
 const path = require( 'path' );
-const log = require( '../../../utils/log' );
+const { workspace, tools, log } = require( 'ckeditor5-dev-utils' );
 
 /**
  * 1. Get CKEditor5 dependencies from package.json file.
@@ -23,10 +21,10 @@ module.exports = ( ckeditor5Path, packageJSON, workspaceRoot ) => {
 	const workspaceAbsolutePath = path.join( ckeditor5Path, workspaceRoot );
 
 	// Get all CKEditor dependencies from package.json.
-	const dependencies = ckeditor5Dirs.getDependencies( packageJSON.dependencies );
+	const dependencies = workspace.getDependencies( packageJSON.dependencies );
 
 	if ( dependencies ) {
-		const directories = ckeditor5Dirs.getDirectories( workspaceAbsolutePath );
+		const directories = workspace.getDirectories( workspaceAbsolutePath );
 
 		if ( directories.length ) {
 			for ( let dependency in dependencies ) {

+ 3 - 5
dev/tasks/dev/tasks/status.js

@@ -5,10 +5,8 @@
 
 'use strict';
 
-const ckeditor5Dirs = require( '../../../utils/ckeditor5-dirs' );
-const git = require( '../../../utils/git' );
 const path = require( 'path' );
-const log = require( '../../../utils/log' );
+const { workspace, git, log } = require( 'ckeditor5-dev-utils' );
 
 /**
  * 1. Get CKEditor5 dependencies from package.json file.
@@ -23,10 +21,10 @@ module.exports = ( ckeditor5Path, packageJSON, workspaceRoot ) => {
 	const workspaceAbsolutePath = path.join( ckeditor5Path, workspaceRoot );
 
 	// Get all CKEditor dependencies from package.json.
-	const dependencies = ckeditor5Dirs.getDependencies( packageJSON.dependencies );
+	const dependencies = workspace.getDependencies( packageJSON.dependencies );
 
 	if ( dependencies ) {
-		const directories = ckeditor5Dirs.getDirectories( workspaceAbsolutePath );
+		const directories = workspace.getDirectories( workspaceAbsolutePath );
 
 		if ( directories.length ) {
 			for ( let dependency in dependencies ) {

+ 4 - 7
dev/tasks/dev/tasks/update.js

@@ -5,11 +5,8 @@
 
 'use strict';
 
-const tools = require( '../../../utils/tools' );
-const ckeditor5Dirs = require( '../../../utils/ckeditor5-dirs' );
-const git = require( '../../../utils/git' );
 const path = require( 'path' );
-const log = require( '../../../utils/log' );
+const { tools, workspace, git, log } = require( 'ckeditor5-dev-utils' );
 
 /**
  * 1. Fetch all branches from each origin in main CKEditor 5 repository.
@@ -39,10 +36,10 @@ module.exports = ( installTask, ckeditor5Path, packageJSON, workspaceRoot, runNp
 	git.fetchAll( ckeditor5Path );
 
 	// Get all CKEditor dependencies from package.json.
-	const dependencies = ckeditor5Dirs.getDependencies( packageJSON.dependencies );
+	const dependencies = workspace.getDependencies( packageJSON.dependencies );
 
 	if ( dependencies ) {
-		const directories = ckeditor5Dirs.getDirectories( workspaceAbsolutePath );
+		const directories = workspace.getDirectories( workspaceAbsolutePath );
 
 		for ( let dependency in dependencies ) {
 			const repositoryURL = dependencies[ dependency ];
@@ -87,7 +84,7 @@ module.exports = ( installTask, ckeditor5Path, packageJSON, workspaceRoot, runNp
 
 	// Remove symlinks not used in this configuration.
 	const nodeModulesPath = path.join( ckeditor5Path, 'node_modules' );
-	const symlinks = ckeditor5Dirs.getSymlinks( nodeModulesPath );
+	const symlinks = workspace.getSymlinks( nodeModulesPath );
 	symlinks
 		.filter( dir => typeof dependencies[ dir ] == 'undefined' )
 		.forEach( dir => {

+ 1 - 1
dev/tasks/exec/functions/git-commit.js

@@ -5,7 +5,7 @@
 
 'use strict';
 
-const git = require( '../../../utils/git' );
+const { git } = require( 'ckeditor5-dev-utils' );
 
 /**
  * Adds only modified files to git repository and commits them with provided message.

+ 1 - 1
dev/tasks/exec/functions/git-push.js

@@ -5,7 +5,7 @@
 
 'use strict';
 
-const git = require( '../../../utils/git' );
+const { git } = require( 'ckeditor5-dev-utils' );
 
 /**
  * Pushes changes of current branch in repository to default origin.

+ 1 - 1
dev/tasks/exec/functions/remove-use-strict.js

@@ -10,7 +10,7 @@ const path = require( 'path' );
 const replace = require( 'gulp-replace' );
 const filterGitignore = require( '../utils/filtergitignore' );
 const filter = require( 'gulp-filter' );
-const tools = require( '../../../utils/tools' );
+const { tools } = require( 'ckeditor5-dev-utils' );
 
 /**
  * Removes lines with `'use strict';` directive.

+ 1 - 1
dev/tasks/exec/functions/sh.js

@@ -5,7 +5,7 @@
 
 'use strict';
 
-const tools = require( '../../../utils/tools' );
+const { tools } = require( 'ckeditor5-dev-utils' );
 
 /**
  * Runs custom shell command over each package.

+ 2 - 3
dev/tasks/exec/tasks.js

@@ -9,8 +9,7 @@ const gulp = require( 'gulp' );
 const minimist = require( 'minimist' );
 const path = require( 'path' );
 const merge = require( 'merge-stream' );
-const log = require( '../../utils/log' );
-const ckeditor5Dirs = require( '../../utils/ckeditor5-dirs' );
+const { log, workspace } = require( 'ckeditor5-dev-utils' );
 
 /**
  * Run task over `ckeditor5-*` repositories.
@@ -81,7 +80,7 @@ function execute( execTask, ckeditor5Path, packageJSON, workspaceRoot, params )
 	const specificRepository = params.repository;
 	const includeRoot = !!params[ 'include-root' ];
 
-	let devDirectories = ckeditor5Dirs.getDevDirectories( workspacePath, packageJSON, ckeditor5Path, includeRoot );
+	let devDirectories = workspace.getDevDirectories( workspacePath, packageJSON, ckeditor5Path, includeRoot );
 
 	if ( specificRepository ) {
 		devDirectories = devDirectories.filter( ( dir ) => {

+ 4 - 5
dev/tasks/test/tasks.js

@@ -10,9 +10,8 @@ const chai = require( 'chai' );
 const filterBy = require( 'gulp-filter-by' );
 const filter = require( 'gulp-filter' );
 const sinon = require( 'sinon' );
-const devTools = require( '../../utils/tools' );
 const semver = require( 'semver' );
-const buildUtils = require( '../build/utils' );
+const { tools, build } = require( 'ckeditor5-dev-utils' );
 const benderConfig = require( '../../../bender' );
 
 /**
@@ -101,7 +100,7 @@ module.exports = () => {
 				.pipe( tasks.skipManual() )
 				.pipe( tasks.skipIgnored() )
 				.pipe( mocha( { reporter: 'progress' } ) )
-				.pipe( tasks.coverage ? istanbul.writeReports() : buildUtils.noop() );
+				.pipe( tasks.coverage ? istanbul.writeReports() : build.noop() );
 		},
 
 		/**
@@ -111,7 +110,7 @@ module.exports = () => {
 		 */
 		skipManual() {
 			return filter( ( file ) => {
-				return !devTools.isFile( file.path.slice( 0, -3 ) + '.md' );
+				return !tools.isFile( file.path.slice( 0, -3 ) + '.md' );
 			} );
 		},
 
@@ -133,7 +132,7 @@ module.exports = () => {
 		devTest() {
 			return gulp.src( 'dev/tests/**/*.js' )
 				.pipe( mocha() )
-				.pipe( tasks.coverage ? istanbul.writeReports() : buildUtils.noop() );
+				.pipe( tasks.coverage ? istanbul.writeReports() : build.noop() );
 		},
 
 		/**

+ 4 - 4
dev/tests/build/tasks.js

@@ -10,7 +10,6 @@
 const mockery = require( 'mockery' );
 const sinon = require( 'sinon' );
 const Vinyl = require( 'vinyl' );
-const utils = require( '../../tasks/build/utils' );
 const babel = require( 'babel-core' );
 const chai = require( 'chai' );
 const expect = chai.expect;
@@ -18,6 +17,7 @@ const gutil = require( 'gulp-util' );
 const gulp = require( 'gulp' );
 const path = require( 'path' );
 const through = require( 'through2' );
+const { build } = require( 'ckeditor5-dev-utils' );
 
 describe( 'build-tasks', () => {
 	let sandbox, tasks;
@@ -103,7 +103,7 @@ describe( 'build-tasks', () => {
 			const code = 'export default {};';
 			sandbox.stub( gutil, 'log' );
 
-			const build = tasks.build.js;
+			const buildTask = tasks.build.js;
 			const stream = require( 'stream' );
 			const files = [
 				new Vinyl( {
@@ -126,7 +126,7 @@ describe( 'build-tasks', () => {
 			} );
 
 			// Stub output stream.
-			sandbox.stub( utils, 'destBuild', () => {
+			sandbox.stub( build, 'destBuild', () => {
 				return through( { objectMode: true }, ( file, encoding, cb ) => {
 					written++;
 
@@ -138,7 +138,7 @@ describe( 'build-tasks', () => {
 				} );
 			} );
 
-			const conversionStream = build( { formats: [ 'amd' ] } );
+			const conversionStream = buildTask( { formats: [ 'amd' ] } );
 
 			conversionStream.on( 'finish', () => {
 				expect( written ).to.equal( 1 );

+ 0 - 789
dev/tests/build/utils.js

@@ -1,789 +0,0 @@
-/**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* global describe, it, beforeEach, afterEach */
-
-'use strict';
-
-const chai = require( 'chai' );
-const expect = chai.expect;
-const sinon = require( 'sinon' );
-const gulp = require( 'gulp' );
-const gutil = require( 'gulp-util' );
-const path = require( 'path' );
-const stream = require( 'stream' );
-const Vinyl = require( 'vinyl' );
-const through = require( 'through2' );
-
-describe( 'build-utils', () => {
-	const utils = require( '../../tasks/build/utils' );
-	let sandbox;
-
-	beforeEach( () => {
-		sandbox = sinon.sandbox.create();
-	} );
-
-	afterEach( () => {
-		sandbox.restore();
-	} );
-
-	describe( 'noop', () => {
-		it( 'should return PassTrough stream', () => {
-			const PassThrough = stream.PassThrough;
-			const ret = utils.noop();
-			expect( ret instanceof PassThrough ).to.equal( true );
-		} );
-
-		it( 'should return a duplex stream when given a callback and call that callback', () => {
-			const spy = sinon.spy();
-			const ret = utils.noop( spy );
-
-			ret.write( 'foo' );
-
-			expect( spy.called ).to.equal( true );
-			expect( ret.writable ).to.equal( true );
-			expect( ret.readable ).to.equal( true );
-		} );
-	} );
-
-	describe( 'destBuild', () => {
-		it( 'should return stream created with gulp.dest', () => {
-			const buildDir = 'build/';
-			const format = 'amd';
-			const destSpy = sandbox.spy( gulp, 'dest' );
-			const stream = utils.destBuild( buildDir, format );
-
-			sinon.assert.calledOnce( destSpy );
-			sinon.assert.calledWithExactly( destSpy, path.join( buildDir, format ) );
-			expect( stream ).to.equal( destSpy.firstCall.returnValue );
-		} );
-	} );
-
-	describe( 'transpile', () => {
-		it( 'should return babel transform stream', ( done ) => {
-			const Stream = stream.Stream;
-			const modulePath = '../files/utils/lib';
-			const appendModuleExtensionSpy = sandbox.spy( utils, 'appendModuleExtension' );
-
-			const babelStream = utils.transpile( 'amd', utils.getBabelOptionsForTests( 'amd' ) );
-
-			expect( babelStream instanceof Stream ).to.equal( true );
-			expect( babelStream.readable ).to.equal( true );
-			expect( babelStream.writable ).to.equal( true );
-
-			babelStream.on( 'finish', () => {
-				sinon.assert.calledOnce( appendModuleExtensionSpy );
-				expect( appendModuleExtensionSpy.args[ 0 ][ 0 ] ).to.equal( modulePath );
-
-				done();
-			} );
-
-			babelStream.pipe(
-				utils.noop( ( file ) => {
-					expect( file.contents.toString() ).to.match( /define\(\'tests\'/ );
-				} )
-			);
-
-			babelStream.write( new Vinyl( {
-				cwd: '/',
-				base: '/test/',
-				path: '/test/file.js',
-				contents: new Buffer( `import * as lib from '${ modulePath }';` )
-			} ) );
-
-			babelStream.end();
-		} );
-
-		it( 'should report error when transpiling fails', ( done ) => {
-			const babelStream = utils.transpile( 'amd' );
-			const utilLogStub = sandbox.stub( gutil, 'log' );
-			const consoleLogStub = sandbox.stub( console, 'log' );
-
-			babelStream.once( 'finish', () => {
-				sinon.assert.calledTwice( utilLogStub );
-				sinon.assert.calledOnce( consoleLogStub );
-				done();
-			} );
-
-			babelStream.write( new Vinyl( {
-				cwd: '/',
-				base: '/test/',
-				path: '/test/file.js',
-				contents: new Buffer( 'class ;' )
-			} ) );
-
-			babelStream.end();
-		} );
-	} );
-
-	describe( 'getBabelOptionsForSource', () => {
-		it( 'should return plugins for amd format', () => {
-			const plugins = [ 'foo' ];
-			sandbox.stub( utils, 'getBabelPlugins', () => plugins );
-
-			const options = utils.getBabelOptionsForSource( 'amd' );
-
-			expect( options ).to.have.property( 'plugins', plugins );
-			expect( options ).to.have.property( 'resolveModuleSource' );
-			expect( options.resolveModuleSource ).to.equal( utils.appendModuleExtension );
-		} );
-
-		it( 'should return plugins for cjs format', () => {
-			const plugins = [ 'foo' ];
-			sandbox.stub( utils, 'getBabelPlugins', () => plugins );
-
-			const options = utils.getBabelOptionsForSource( 'cjs' );
-
-			expect( options ).to.have.property( 'plugins', plugins );
-			expect( options ).to.have.property( 'resolveModuleSource' );
-			expect( options.resolveModuleSource ).to.equal( utils.resolveModuleSource );
-		} );
-	} );
-
-	describe( 'getBabelOptionsForTests', () => {
-		it( 'should return plugins for amd format', () => {
-			const plugins = [ 'foo' ];
-			sandbox.stub( utils, 'getBabelPlugins', () => plugins );
-
-			const options = utils.getBabelOptionsForTests( 'amd' );
-
-			expect( options ).to.have.property( 'plugins', plugins );
-			expect( options ).to.have.property( 'resolveModuleSource' );
-			expect( options ).to.have.property( 'moduleIds', true );
-			expect( options ).to.have.property( 'moduleId', 'tests' );
-			expect( options.resolveModuleSource ).to.equal( utils.appendModuleExtension );
-		} );
-
-		it( 'should return plugins for cjs format', () => {
-			const plugins = [ 'foo' ];
-			sandbox.stub( utils, 'getBabelPlugins', () => plugins );
-
-			const options = utils.getBabelOptionsForTests( 'cjs' );
-
-			expect( options ).to.have.property( 'plugins', plugins );
-			expect( options ).to.have.property( 'resolveModuleSource' );
-			expect( options ).to.have.property( 'moduleIds', true );
-			expect( options ).to.have.property( 'moduleId', 'tests' );
-			expect( options.resolveModuleSource ).to.equal( utils.resolveModuleSource );
-		} );
-	} );
-
-	describe( 'getBabelPlugins', () => {
-		it( 'should return plugins for amd format', () => {
-			expect( utils.getBabelPlugins( 'amd' ) ).to.be.an( 'array' );
-		} );
-
-		it( 'should return plugins for cjs format', () => {
-			expect( utils.getBabelPlugins( 'cjs' ) ).to.be.an( 'array' );
-		} );
-
-		it( 'should throw an exception when incorrect format is provided', () => {
-			const format = 'incorrect-format';
-
-			expect( () => {
-				utils.getBabelPlugins( format );
-			} ).to.throw( Error, `Incorrect format: ${ format }` );
-		} );
-	} );
-
-	describe( 'getConversionStreamGenerator', () => {
-		beforeEach( () => {
-			sandbox.stub( utils, 'getBabelOptionsForSource', () => 'src' );
-			sandbox.stub( utils, 'getBabelOptionsForTests', () => 'tests' );
-
-			// Stub to avoid writing to the fs.
-			sandbox.stub( utils, 'destBuild', () => utils.noop() );
-
-			// The transpile converted with append to file contents what was
-			// passed to it as an options object and that's a result of getBabelOptions*,
-			// which is stubbed above (will return 'src' or 'tests').
-			sandbox.stub( utils, 'transpile', ( format, options ) => {
-				return through( { objectMode: true }, ( file, encoding, callback ) => {
-					file.contents = new Buffer( file.contents.toString() + ';' + format + ';' + options );
-
-					callback( null, file );
-				} );
-			} );
-
-			sandbox.stub( utils, 'appendBenderLauncher', () => {
-				return through( { objectMode: true }, ( file, encoding, callback ) => {
-					file.contents = new Buffer( file.contents.toString() + ';launcher' );
-
-					callback( null, file );
-				} );
-			} );
-		} );
-
-		it( 'should return function that can be used for creating conversion streams', () => {
-			const buildDir = 'build/';
-			const formats = [ 'amd', 'cjs', 'esnext' ];
-			const fn = utils.getConversionStreamGenerator( buildDir );
-			const streams = formats.reduce( fn, [] );
-
-			expect( streams.length ).to.equal( formats.length );
-		} );
-
-		describe( 'created conversion stream', () => {
-			it( 'should process source JS file', ( done ) => {
-				const buildDir = 'build/';
-				const formats = [ 'amd' ];
-				const fn = utils.getConversionStreamGenerator( buildDir );
-				const streams = formats.reduce( fn, [] );
-
-				expect( streams ).to.have.length( 1 );
-
-				const stream = streams[ 0 ];
-
-				stream.pipe(
-					utils.noop( ( file ) => {
-						expect( file.contents.toString() ).to.equal( 'foo();amd;src' );
-						done();
-					} )
-				);
-
-				stream.write( new Vinyl( {
-					cwd: './',
-					path: 'ckeditor5/core/file.js',
-					contents: new Buffer( 'foo()' )
-				} ) );
-			} );
-		} );
-
-		describe( 'created conversion stream', () => {
-			it( 'should process test file in amd format', ( done ) => {
-				const buildDir = 'build/';
-				const formats = [ 'amd' ];
-				const fn = utils.getConversionStreamGenerator( buildDir );
-				const streams = formats.reduce( fn, [] );
-
-				expect( streams ).to.have.length( 1 );
-
-				const stream = streams[ 0 ];
-
-				stream.pipe(
-					utils.noop( ( file ) => {
-						expect( file.contents.toString() ).to.equal( 'foo();amd;tests;launcher' );
-						done();
-					} )
-				);
-
-				stream.write( new Vinyl( {
-					cwd: './',
-					path: 'tests/core/file.js',
-					contents: new Buffer( 'foo()' )
-				} ) );
-			} );
-
-			it( 'should process test file in cjs format', ( done ) => {
-				const buildDir = 'build/';
-				const formats = [ 'cjs' ];
-				const fn = utils.getConversionStreamGenerator( buildDir );
-				const streams = formats.reduce( fn, [] );
-
-				expect( streams ).to.have.length( 1 );
-
-				const stream = streams[ 0 ];
-
-				stream.pipe(
-					utils.noop( ( file ) => {
-						expect( file.contents.toString() ).to.equal( 'foo();cjs;tests' );
-						done();
-					} )
-				);
-
-				stream.write( new Vinyl( {
-					cwd: './',
-					path: 'tests/core/file.js',
-					contents: new Buffer( 'foo()' )
-				} ) );
-			} );
-		} );
-	} );
-
-	describe( 'pickVersionedFile', () => {
-		it( 'should rename file for provided format', ( done ) => {
-			const rename = utils.pickVersionedFile( 'amd' );
-
-			rename.pipe(
-				utils.noop( ( data ) => {
-					expect( data.basename ).to.equal( 'load.js' );
-					done();
-				} )
-			);
-
-			rename.write( new Vinyl( {
-				cwd: '/',
-				base: '/test/',
-				path: '/test/load__amd.js',
-				contents: new Buffer( '' )
-			} ) );
-
-			rename.end();
-		} );
-
-		it( 'should remove files in other formats', ( done ) => {
-			const rename = utils.pickVersionedFile( 'amd' );
-			const spy = sandbox.spy( ( data ) => {
-				expect( data.basename ).to.equal( 'load.js' );
-			} );
-
-			rename.pipe(
-				utils.noop( spy )
-			);
-
-			rename.on( 'end', () => {
-				sinon.assert.calledOnce( spy );
-				done();
-			} );
-
-			const amd = new Vinyl( {
-				cwd: '/',
-				base: '/test/',
-				path: '/test/load__amd.js',
-				contents: new Buffer( '' )
-			} );
-
-			const cjs = new Vinyl( {
-				cwd: '/',
-				base: '/test/',
-				path: '/test/load__cjs.js',
-				contents: new Buffer( '' )
-			} );
-
-			const esnext = new Vinyl( {
-				cwd: '/',
-				base: '/test/',
-				path: '/test/load__esnext.js',
-				contents: new Buffer( '' )
-			} );
-
-			rename.write( cjs );
-			rename.write( amd );
-			rename.write( esnext );
-			rename.end();
-		} );
-	} );
-
-	describe( 'renamePackageFiles', () => {
-		it( 'should move source files to correct directories', ( done ) => {
-			const rename = utils.renamePackageFiles();
-
-			rename.pipe(
-				utils.noop( ( data ) => {
-					expect( data.path ).to.equal( path.normalize( 'ckeditor5/core/foo/file.js' ) );
-					done();
-				} )
-			);
-
-			rename.write( new Vinyl( {
-				cwd: './',
-				path: path.normalize( 'ckeditor5-core/src/foo/file.js' ),
-				contents: new Buffer( '' )
-			} ) );
-
-			rename.end();
-		} );
-
-		it( 'should move test files to correct directories', ( done ) => {
-			const rename = utils.renamePackageFiles();
-
-			rename.pipe(
-				utils.noop( ( data ) => {
-					expect( data.path ).to.equal( path.normalize( 'tests/core/foo/file.js' ) );
-					done();
-				} )
-			);
-
-			rename.write( new Vinyl( {
-				cwd: './',
-				path: path.normalize( 'ckeditor5-core/tests/foo/file.js' ),
-				contents: new Buffer( '' )
-			} ) );
-
-			rename.end();
-		} );
-
-		it( 'should throw error when wrong path provided 1', () => {
-			const rename = utils.renamePackageFiles();
-
-			expect( () => {
-				rename.write( new Vinyl( {
-					cwd: './',
-					path: 'plugin/src/file.js',
-					contents: new Buffer( '' )
-				} ) );
-			} ).to.throw( Error );
-		} );
-
-		it( 'should throw error when wrong path provided 2', () => {
-			const rename = utils.renamePackageFiles();
-
-			expect( () => {
-				rename.write( new Vinyl( {
-					cwd: './',
-					path: 'ckeditor5-core/file.js',
-					contents: new Buffer( '' )
-				} ) );
-			} ).to.throw( Error );
-		} );
-	} );
-
-	describe( 'renameCKEditor5Files', () => {
-		it( 'should move source files to correct directories', ( done ) => {
-			const rename = utils.renameCKEditor5Files();
-
-			rename.pipe(
-				utils.noop( ( data ) => {
-					expect( data.path ).to.equal( path.normalize( 'ckeditor5/foo/file.js' ) );
-					done();
-				} )
-			);
-
-			rename.write( new Vinyl( {
-				cwd: './',
-				path: path.normalize( 'src/foo/file.js' ),
-				contents: new Buffer( '' )
-			} ) );
-
-			rename.end();
-		} );
-
-		it( 'should move test files to correct directories', ( done ) => {
-			const rename = utils.renameCKEditor5Files();
-
-			rename.pipe(
-				utils.noop( ( data ) => {
-					expect( data.path ).to.equal( path.normalize( 'tests/ckeditor5/foo/file.js' ) );
-					done();
-				} )
-			);
-
-			rename.write( new Vinyl( {
-				cwd: './',
-				path: path.normalize( 'tests/foo/file.js' ),
-				contents: new Buffer( '' )
-			} ) );
-
-			rename.end();
-		} );
-
-		it( 'should throw error when wrong path provided 1', () => {
-			const rename = utils.renameCKEditor5Files();
-
-			expect( () => {
-				rename.write( new Vinyl( {
-					cwd: './',
-					path: 'plugin/src/file.js',
-					contents: new Buffer( '' )
-				} ) );
-			} ).to.throw( Error );
-		} );
-	} );
-
-	describe( 'appendModuleExtension', () => {
-		it( 'appends module extension when path provided', () => {
-			const filePath = './path/to/file';
-			const source = utils.appendModuleExtension( filePath );
-
-			expect( source ).to.equal( filePath + '.js' );
-		} );
-
-		it( 'appends module extension when URL is provided', () => {
-			const url = 'http://example.com/lib';
-			const source = utils.appendModuleExtension( url );
-
-			expect( source ).to.equal( url + '.js' );
-		} );
-
-		it( 'returns unchanged if module is provided', () => {
-			const module = 'lib/module';
-			const source = utils.appendModuleExtension( module );
-
-			expect( source ).to.equal( module );
-		} );
-	} );
-
-	describe( 'appendBenderLauncher', () => {
-		it( 'appends the launcher code to a file', ( done ) => {
-			const stream = utils.appendBenderLauncher();
-
-			stream.pipe(
-				utils.noop( ( data ) => {
-					expect( data.contents.toString() ).equal( 'foo();' + utils.benderLauncherCode );
-					done();
-				} )
-			);
-
-			stream.write( new Vinyl( {
-				cwd: './',
-				path: 'tests/file.js',
-				contents: new Buffer( 'foo();' )
-			} ) );
-
-			stream.end();
-		} );
-
-		// #62
-		it( 'does nothing to a null file', ( done ) => {
-			const stream = utils.appendBenderLauncher();
-
-			stream.pipe(
-				utils.noop( ( data ) => {
-					expect( data.contents ).to.equal( null );
-					done();
-				} )
-			);
-
-			stream.write( new Vinyl( {
-				cwd: './',
-				path: 'tests/file.js',
-				contents: null
-			} ) );
-
-			stream.end();
-		} );
-	} );
-
-	describe( 'isTestFile', () => {
-		function test( path, expected ) {
-			it( `returns ${ expected} for ${ path }`, () => {
-				const file = new Vinyl( {
-					cwd: './',
-					path: path,
-					contents: new Buffer( '' )
-				} );
-
-				expect( utils.isTestFile( file ) ).to.equal( expected );
-			} );
-		}
-
-		test( 'tests/file.js', true );
-		test( 'tests/foo/file.js', true );
-		test( 'tests/tests.js', true );
-		test( 'tests/_utils-tests/foo.js', true );
-
-		test( 'foo/file.js', false );
-		test( 'foo/tests/file.js', false );
-		test( 'tests/_foo/file.js', false );
-	} );
-
-	describe( 'getPackages', () => {
-		it( 'returns collected paths to ckeditor5-* packages', ( done ) => {
-			const fs = require( 'fs' );
-			const readDirStub = sandbox.stub( fs, 'readdirSync', () => {
-				return [
-					'ckeditor5-core',
-					'ckeditor5-theme-default'
-				];
-			} );
-			const statStub = sandbox.stub( fs, 'lstatSync', () => {
-				return {
-					isDirectory() {
-						return true;
-					},
-					isSymbolicLink() {
-						return false;
-					}
-				};
-			} );
-
-			expect( utils.getPackages( '.' ) ).to.have.members( [
-				'node_modules/ckeditor5-core',
-				'node_modules/ckeditor5-theme-default'
-			] );
-
-			sinon.assert.calledOnce( readDirStub );
-			sinon.assert.calledTwice( statStub );
-
-			done();
-		} );
-	} );
-
-	describe( 'filterThemeEntryPoints', () => {
-		it( 'returns a stream containing theme entry points only', ( done ) => {
-			const stream = require( 'stream' );
-			const entryPoints = [];
-
-			function fakeInputStream() {
-				const files = [
-					new Vinyl( {
-						cwd: './',
-						path: 'foo/bar/_helper.scss',
-						contents: new Buffer( '' )
-					} ),
-					new Vinyl( {
-						cwd: './',
-						path: 'foo/bar/component.scss',
-						contents: new Buffer( '' )
-					} ),
-					new Vinyl( {
-						cwd: './',
-						path: 'foo/bar/theme.scss',
-						contents: new Buffer( '' )
-					} ),
-					new Vinyl( {
-						cwd: './',
-						path: 'foo/bar/_theme.scss',
-						contents: new Buffer( '' )
-					} )
-				];
-
-				const fake = new stream.Readable( { objectMode: true } );
-
-				fake._read = () => {
-					fake.push( files.pop() || null );
-				};
-
-				return fake;
-			}
-
-			fakeInputStream()
-				.pipe( utils.filterThemeEntryPoints() )
-				.pipe( through.obj( ( file, encoding, callback ) => {
-					entryPoints.push( file.path );
-
-					callback();
-				}, () => {
-					expect( entryPoints ).to.have.members( [ 'foo/bar/theme.scss' ] );
-
-					done();
-				} ) );
-		} );
-	} );
-
-	describe( 'compileThemes', () => {
-		it( 'returns a stream containing compiled CSS file', ( done ) => {
-			const stream = require( 'stream' );
-			let compiledThemePath;
-			let compiledThemeCss;
-
-			function fakeInputStream() {
-				const files = [
-					new Vinyl( {
-						cwd: './',
-						path: 'aaa/aaa/theme.scss',
-						contents: new Buffer( '' )
-					} ),
-					new Vinyl( {
-						cwd: './',
-						path: 'zzz/ckeditor5-theme-quz/theme.scss',
-						contents: new Buffer( '' )
-					} ),
-					new Vinyl( {
-						cwd: './',
-						path: 'C:\\win\\dows\\theme.scss',
-						contents: new Buffer( '' )
-					} )
-				];
-
-				const fake = new stream.Readable( { objectMode: true } );
-
-				fake._read = () => {
-					fake.push( files.pop() || null );
-				};
-
-				return fake;
-			}
-
-			sandbox.stub( utils, 'getSassOptions', dataToRender => {
-				return {
-					data: dataToRender,
-					outputStyle: 'expanded',
-					importer: url => {
-						return { file: url, contents: `/*! ${ url } */` };
-					}
-				};
-			} );
-
-			fakeInputStream()
-				.pipe( utils.compileThemes( 'abc.css' ) )
-				.pipe( through.obj( ( file, encoding, callback ) => {
-					compiledThemePath = file.path;
-					compiledThemeCss = file.contents;
-
-					callback();
-				}, () => {
-					expect( compiledThemePath ).to.be.equal( 'abc.css' );
-					expect( compiledThemeCss.toString() ).to.be.equal(
-// Note: Order matters. The first one should be ckeditor5-theme-* in order
-// to provide necessary dependencies (mixins, vars) for the following files.
-`/*! zzz/ckeditor5-theme-quz/theme.scss */
-/*! aaa/aaa/theme.scss */
-/*! C:\\win\\dows\\theme.scss */
-` );
-
-					done();
-				} ) );
-		} );
-	} );
-
-	describe( 'getSassOptions', () => {
-		it( 'should return default options for SASS', () => {
-			const options = utils.getSassOptions( 'foo' );
-
-			expect( options ).to.have.property( 'data', 'foo' );
-			expect( options ).to.have.property( 'sourceMap', true );
-			expect( options ).to.have.property( 'sourceMapEmbed', true );
-			expect( options ).to.have.property( 'outputStyle', 'expanded' );
-			expect( options ).to.have.property( 'sourceComments', true );
-		} );
-	} );
-
-	describe( 'parseArguments', () => {
-		it( 'returns object with defaults', () => {
-			const args = utils.parseArguments();
-
-			expect( args.formats ).to.have.members( [ 'amd' ] );
-			expect( args.watch ).to.be.equal( false );
-		} );
-	} );
-
-	describe( 'getIconSpriteOptions', () => {
-		it( 'returns object with defaults', () => {
-			const options = utils.getIconSpriteOptions();
-
-			expect( options ).to.have.all.keys( [ 'shape', 'svg', 'mode' ] );
-		} );
-
-		it( 'returns icon ids generator out of svg file names', () => {
-			const options = utils.getIconSpriteOptions();
-
-			expect( options.shape.id.generator( 'foo.svg' ) ).to.equal( 'ck-icon-foo' );
-			expect( options.shape.id.generator( 'foo/bar/foo.svg' ) ).to.equal( 'ck-icon-foo' );
-			expect( options.shape.id.generator( 'C:\\foo\\foo.svg' ) ).to.equal( 'ck-icon-foo' );
-		} );
-
-		it( 'returns configuration to output JavaScript sprite', () => {
-			const options = utils.getIconSpriteOptions();
-
-			expect( options.mode.symbol.render.js.dest ).to.equal( 'iconmanagermodel.js' );
-		} );
-	} );
-
-	describe( 'getThemeFormatDestStreams', () => {
-		it( 'returns array of streams for each format', () => {
-			const streams = utils.getThemeFormatDestStreams( 'foo', [ 'a', 'b' ] );
-
-			expect( streams ).to.be.an( 'array' );
-			expect( streams ).to.have.length( 2 );
-		} );
-	} );
-
-	describe( 'resolveModuleSource', () => {
-		it( 'does not modify relative source paths', () => {
-			const source = '../module';
-			const resolved = utils.resolveModuleSource( source, '' );
-			expect( resolved ).to.equal( source );
-		} );
-
-		it( 'resolves absolute source paths', () => {
-			const source = '/ckeditor5/path/to/module.js';
-			const file = path.join( process.cwd(), 'tests', 'module', 'module.js' );
-
-			const resolved = utils.resolveModuleSource( source, file );
-			expect( resolved ).to.equal( '../../ckeditor5/path/to/module.js' );
-		} );
-	} );
-} );

+ 1 - 2
dev/tests/dev/create-package.js

@@ -10,10 +10,9 @@
 const chai = require( 'chai' );
 const sinon = require( 'sinon' );
 const expect = chai.expect;
-const tools = require( '../../utils/tools' );
 const inquiries = require( '../../tasks/dev/utils/inquiries' );
-const git = require( '../../utils/git' );
 const path = require( 'path' );
+const { tools, git } = require( 'ckeditor5-dev-utils' );
 
 describe( 'dev-create-package', () => {
 	let spies;

+ 3 - 3
dev/tests/dev/init.js

@@ -8,7 +8,7 @@
 'use strict';
 
 const sinon = require( 'sinon' );
-const ckeditor5Dirs = require( '../../utils/ckeditor5-dirs' );
+const { workspace } = require( 'ckeditor5-dev-utils' );
 
 describe( 'dev-init', () => {
 	const initTask = require( '../../tasks/dev/tasks/init' );
@@ -16,7 +16,7 @@ describe( 'dev-init', () => {
 	const workspaceRoot = '..';
 
 	it( 'should get all ckedtior5- dependencies and execute dev-install on them', () => {
-		const getDependenciesSpy = sinon.spy( ckeditor5Dirs, 'getDependencies' );
+		const getDependenciesSpy = sinon.spy( workspace, 'getDependencies' );
 		const installSpy = sinon.spy();
 		const JSON = {
 			dependencies: {
@@ -39,7 +39,7 @@ describe( 'dev-init', () => {
 	} );
 
 	it( 'should not call dev-install if no ckedtior5- dependencies', () => {
-		const getDependenciesSpy = sinon.spy( ckeditor5Dirs, 'getDependencies' );
+		const getDependenciesSpy = sinon.spy( workspace, 'getDependencies' );
 		const installSpy = sinon.spy();
 		const JSON = {
 			dependencies: {}

+ 1 - 2
dev/tests/dev/install.js

@@ -9,11 +9,10 @@
 
 const chai = require( 'chai' );
 const sinon = require( 'sinon' );
-const git = require( '../../utils/git' );
-const tools = require( '../../utils/tools' );
 const installTask = require( '../../tasks/dev/tasks/install' );
 const expect = chai.expect;
 const path = require( 'path' );
+const { tools, git } = require( 'ckeditor5-dev-utils' );
 
 describe( 'dev-install', () => {
 	const moduleName = 'ckeditor5-core';

+ 10 - 11
dev/tests/dev/relink.js

@@ -8,9 +8,8 @@
 'use strict';
 
 const sinon = require( 'sinon' );
-const tools = require( '../../utils/tools' );
-const ckeditor5Dirs = require( '../../utils/ckeditor5-dirs' );
 const path = require( 'path' );
+const { tools, workspace } = require( 'ckeditor5-dev-utils' );
 
 describe( 'dev-relink', () => {
 	const task = require( '../../tasks/dev/tasks/relink' );
@@ -21,8 +20,8 @@ describe( 'dev-relink', () => {
 
 	it( 'should link dev repositories', () => {
 		const dirs = [ 'ckeditor5-core', 'ckeditor5-devtest' ];
-		const getDependenciesSpy = sinon.spy( ckeditor5Dirs, 'getDependencies' );
-		const getDirectoriesStub = sinon.stub( ckeditor5Dirs, 'getDirectories' ).returns( dirs );
+		const getDependenciesSpy = sinon.spy( workspace, 'getDependencies' );
+		const getDirectoriesStub = sinon.stub( workspace, 'getDirectories' ).returns( dirs );
 		const linkStub = sinon.stub( tools, 'linkDirectories' );
 		const json = {
 			dependencies: {
@@ -44,8 +43,8 @@ describe( 'dev-relink', () => {
 	} );
 
 	it( 'should not link when no dependencies are found', () => {
-		const getDependenciesSpy = sinon.spy( ckeditor5Dirs, 'getDependencies' );
-		const getDirectoriesStub = sinon.stub( ckeditor5Dirs, 'getDirectories' );
+		const getDependenciesSpy = sinon.spy( workspace, 'getDependencies' );
+		const getDirectoriesStub = sinon.stub( workspace, 'getDirectories' );
 		const linkStub = sinon.stub( tools, 'linkDirectories' );
 		const json = {
 			dependencies: {
@@ -63,8 +62,8 @@ describe( 'dev-relink', () => {
 	} );
 
 	it( 'should not link when no plugins in dev mode', () => {
-		const getDependenciesSpy = sinon.spy( ckeditor5Dirs, 'getDependencies' );
-		const getDirectoriesStub = sinon.stub( ckeditor5Dirs, 'getDirectories' ).returns( [] );
+		const getDependenciesSpy = sinon.spy( workspace, 'getDependencies' );
+		const getDirectoriesStub = sinon.stub( workspace, 'getDirectories' ).returns( [] );
 		const linkStub = sinon.stub( tools, 'linkDirectories' );
 		const json = {
 			dependencies: {
@@ -84,8 +83,8 @@ describe( 'dev-relink', () => {
 
 	it( 'should write error message when linking is unsuccessful', () => {
 		const dirs = [ 'ckeditor5-core' ];
-		const getDependenciesSpy = sinon.spy( ckeditor5Dirs, 'getDependencies' );
-		const getDirectoriesStub = sinon.stub( ckeditor5Dirs, 'getDirectories' ).returns( dirs );
+		const getDependenciesSpy = sinon.spy( workspace, 'getDependencies' );
+		const getDirectoriesStub = sinon.stub( workspace, 'getDirectories' ).returns( dirs );
 		const error = new Error( 'Error message.' );
 		const linkStub = sinon.stub( tools, 'linkDirectories' ).throws( error );
 		const json = {
@@ -96,7 +95,7 @@ describe( 'dev-relink', () => {
 			}
 		};
 		const writeErrorSpy = sinon.spy();
-		const log = require( '../../utils/log' );
+		const { log } = require( 'ckeditor5-dev-utils' );
 		log.configure( () => {}, writeErrorSpy );
 
 		task( ckeditor5Path, json, workspaceRoot );

+ 10 - 11
dev/tests/dev/status.js

@@ -8,12 +8,11 @@
 'use strict';
 
 const sinon = require( 'sinon' );
-const ckeditor5Dirs = require( '../../utils/ckeditor5-dirs' );
-const git = require( '../../utils/git' );
 const path = require( 'path' );
 const chai = require( 'chai' );
 const expect = chai.expect;
 const gulp = require( 'gulp' );
+const { workspace, git } = require( 'ckeditor5-dev-utils' );
 
 describe( 'dev-status', () => {
 	const statusTask = require( '../../tasks/dev/tasks/status' );
@@ -23,8 +22,8 @@ describe( 'dev-status', () => {
 
 	it( 'should show status of dev repositories', () => {
 		const dirs = [ 'ckeditor5-core', 'ckeditor5-devtest' ];
-		const getDependenciesSpy = sinon.spy( ckeditor5Dirs, 'getDependencies' );
-		const getDirectoriesStub = sinon.stub( ckeditor5Dirs, 'getDirectories' ).returns( dirs );
+		const getDependenciesSpy = sinon.spy( workspace, 'getDependencies' );
+		const getDirectoriesStub = sinon.stub( workspace, 'getDirectories' ).returns( dirs );
 		const statusStub = sinon.stub( git, 'getStatus' );
 		const json = {
 			dependencies: {
@@ -46,8 +45,8 @@ describe( 'dev-status', () => {
 	} );
 
 	it( 'should not get status when no dependencies are found', () => {
-		const getDependenciesSpy = sinon.spy( ckeditor5Dirs, 'getDependencies' );
-		const getDirectoriesStub = sinon.stub( ckeditor5Dirs, 'getDirectories' );
+		const getDependenciesSpy = sinon.spy( workspace, 'getDependencies' );
+		const getDirectoriesStub = sinon.stub( workspace, 'getDirectories' );
 		const statusStub = sinon.stub( git, 'getStatus' );
 		const json = {
 			dependencies: {
@@ -65,8 +64,8 @@ describe( 'dev-status', () => {
 	} );
 
 	it( 'should not get status when no plugins in dev mode', () => {
-		const getDependenciesSpy = sinon.spy( ckeditor5Dirs, 'getDependencies' );
-		const getDirectoriesStub = sinon.stub( ckeditor5Dirs, 'getDirectories' ).returns( [] );
+		const getDependenciesSpy = sinon.spy( workspace, 'getDependencies' );
+		const getDirectoriesStub = sinon.stub( workspace, 'getDirectories' ).returns( [] );
 		const statusStub = sinon.stub( git, 'getStatus' );
 		const json = {
 			dependencies: {
@@ -86,8 +85,8 @@ describe( 'dev-status', () => {
 
 	it( 'should write error message when getStatus is unsuccessful', () => {
 		const dirs = [ 'ckeditor5-core' ];
-		const getDependenciesSpy = sinon.spy( ckeditor5Dirs, 'getDependencies' );
-		const getDirectoriesStub = sinon.stub( ckeditor5Dirs, 'getDirectories' ).returns( dirs );
+		const getDependenciesSpy = sinon.spy( workspace, 'getDependencies' );
+		const getDirectoriesStub = sinon.stub( workspace, 'getDirectories' ).returns( dirs );
 		const error = new Error( 'Error message.' );
 		const statusStub = sinon.stub( git, 'getStatus' ).throws( error );
 		const json = {
@@ -98,7 +97,7 @@ describe( 'dev-status', () => {
 			}
 		};
 		const writeErrorSpy = sinon.spy();
-		const log = require( '../../utils/log' );
+		const { log } = require( 'ckeditor5-dev-utils' );
 		log.configure( () => {}, writeErrorSpy );
 
 		statusTask( ckeditor5Path, json, workspaceRoot );

+ 14 - 16
dev/tests/dev/update.js

@@ -8,13 +8,11 @@
 'use strict';
 
 const sinon = require( 'sinon' );
-const tools = require( '../../utils/tools' );
-const ckeditor5Dirs = require( '../../utils/ckeditor5-dirs' );
-const git = require( '../../utils/git' );
 const path = require( 'path' );
 const chai = require( 'chai' );
 const expect = chai.expect;
 const gulp = require( 'gulp' );
+const { tools, workspace, git } = require( 'ckeditor5-dev-utils' );
 
 describe( 'dev-update', () => {
 	const updateTask = require( '../../tasks/dev/tasks/update' );
@@ -24,7 +22,7 @@ describe( 'dev-update', () => {
 	const spies = {};
 
 	beforeEach( () => {
-		spies.getDependencies = sinon.spy( ckeditor5Dirs, 'getDependencies' );
+		spies.getDependencies = sinon.spy( workspace, 'getDependencies' );
 		spies.checkout = sinon.stub( git, 'checkout' );
 		spies.pull = sinon.stub( git, 'pull' );
 		spies.fetchAll = sinon.stub( git, 'fetchAll' );
@@ -40,8 +38,8 @@ describe( 'dev-update', () => {
 	it( 'should update dev repositories', () => {
 		const dirs = [ 'ckeditor5-core', 'ckeditor5-devtest' ];
 		const installTask = sinon.spy();
-		spies.getDirectories = sinon.stub( ckeditor5Dirs, 'getDirectories' ).returns( dirs );
-		spies.getSymlinks = sinon.stub( ckeditor5Dirs, 'getSymlinks' ).returns( [] );
+		spies.getDirectories = sinon.stub( workspace, 'getDirectories' ).returns( dirs );
+		spies.getSymlinks = sinon.stub( workspace, 'getSymlinks' ).returns( [] );
 
 		const json = {
 			dependencies: {
@@ -80,8 +78,8 @@ describe( 'dev-update', () => {
 	it( 'should install missing dependencies', () => {
 		const dirs = [ 'ckeditor5-core', 'ckeditor5-devtest' ];
 		const installTask = sinon.spy();
-		spies.getDirectories = sinon.stub( ckeditor5Dirs, 'getDirectories' ).returns( dirs );
-		spies.getSymlinks = sinon.stub( ckeditor5Dirs, 'getSymlinks' ).returns( [] );
+		spies.getDirectories = sinon.stub( workspace, 'getDirectories' ).returns( dirs );
+		spies.getSymlinks = sinon.stub( workspace, 'getSymlinks' ).returns( [] );
 
 		const json = {
 			dependencies: {
@@ -123,8 +121,8 @@ describe( 'dev-update', () => {
 	it( 'should remove symlinks that are not needed', () => {
 		const dirs = [ 'ckeditor5-core', 'ckeditor5-devtest' ];
 		const installTask = sinon.spy();
-		spies.getDirectories = sinon.stub( ckeditor5Dirs, 'getDirectories' ).returns( dirs );
-		spies.getSymlinks = sinon.stub( ckeditor5Dirs, 'getSymlinks' ).returns( [ 'ckeditor5-unused' ] );
+		spies.getDirectories = sinon.stub( workspace, 'getDirectories' ).returns( dirs );
+		spies.getSymlinks = sinon.stub( workspace, 'getSymlinks' ).returns( [ 'ckeditor5-unused' ] );
 
 		const json = {
 			dependencies: {
@@ -163,13 +161,13 @@ describe( 'dev-update', () => {
 	} );
 
 	it( 'should catch linking errors', () => {
-		const log = require( '../../utils/log' );
+		const { log } = require( 'ckeditor5-dev-utils' );
 		const dirs = [ 'ckeditor5-core', 'ckeditor5-devtest' ];
 		const installTask = sinon.spy();
 		const outSpy = sinon.spy();
 		const errSpy = sinon.spy();
-		spies.getDirectories = sinon.stub( ckeditor5Dirs, 'getDirectories' ).returns( dirs );
-		spies.getSymlinks = sinon.stub( ckeditor5Dirs, 'getSymlinks' ).returns( [ 'ckeditor5-unused' ] );
+		spies.getDirectories = sinon.stub( workspace, 'getDirectories' ).returns( dirs );
+		spies.getSymlinks = sinon.stub( workspace, 'getSymlinks' ).returns( [ 'ckeditor5-unused' ] );
 		spies.linkDirectories.throws();
 
 		log.configure( outSpy, errSpy );
@@ -210,11 +208,11 @@ describe( 'dev-update', () => {
 
 	it( 'should skip updating if no dependencies found and fetch only main repository', () => {
 		spies.getDependencies.restore();
-		spies.getDependencies = sinon.stub( ckeditor5Dirs, 'getDependencies' ).returns( null );
+		spies.getDependencies = sinon.stub( workspace, 'getDependencies' ).returns( null );
 		const dirs = [ 'ckeditor5-core', 'ckeditor5-devtest' ];
 		const installTask = sinon.spy();
-		spies.getDirectories = sinon.stub( ckeditor5Dirs, 'getDirectories' ).returns( dirs );
-		spies.getSymlinks = sinon.stub( ckeditor5Dirs, 'getSymlinks' ).returns( [] );
+		spies.getDirectories = sinon.stub( workspace, 'getDirectories' ).returns( dirs );
+		spies.getSymlinks = sinon.stub( workspace, 'getSymlinks' ).returns( [] );
 
 		const json = {
 			dependencies: {

+ 10 - 12
dev/tests/exec/tasks.js

@@ -45,7 +45,7 @@ describe( 'exec-tasks', () => {
 	describe( 'execOnRepositories', () => {
 		it( 'should throw error when there is no specified task', () => {
 			const errorMessage = 'Missing task parameter: --task task-name';
-			const log = require( '../../utils/log' );
+			const { log } = require( 'ckeditor5-dev-utils' );
 			const logErrSpy = sandbox.stub( log, 'err' );
 
 			mockery.registerMock( 'minimist', () => {
@@ -61,7 +61,7 @@ describe( 'exec-tasks', () => {
 		} );
 
 		it( 'should throw error when task cannot be found', () => {
-			const log = require( '../../utils/log' );
+			const { log } = require( 'ckeditor5-dev-utils' );
 			const logErrSpy = sandbox.stub( log, 'err' );
 
 			mockery.registerMock( 'minimist', () => {
@@ -77,11 +77,10 @@ describe( 'exec-tasks', () => {
 		} );
 
 		it( 'should load task module', () => {
-			const ckeditor5Dirs = require( '../../utils/ckeditor5-dirs' );
-			const log = require( '../../utils/log' );
+			const { workspace, log } = require( 'ckeditor5-dev-utils' );
 			const logErrSpy = sandbox.stub( log, 'err' );
 
-			sandbox.stub( ckeditor5Dirs, 'getDevDirectories' ).returns( [] );
+			sandbox.stub( workspace, 'getDevDirectories' ).returns( [] );
 			mockery.registerMock( 'minimist', () => {
 				return { task: 'task-to-run' };
 			} );
@@ -94,9 +93,8 @@ describe( 'exec-tasks', () => {
 		} );
 
 		it( 'should log error when task is throwing exceptions', () => {
-			const ckeditor5Dirs = require( '../../utils/ckeditor5-dirs' );
+			const { workspace, log } = require( 'ckeditor5-dev-utils' );
 			const taskStub = sinon.stub();
-			const log = require( '../../utils/log' );
 			const logErrSpy = sandbox.stub( log, 'err' );
 
 			taskStub.onSecondCall().throws();
@@ -104,7 +102,7 @@ describe( 'exec-tasks', () => {
 			mockery.registerMock( 'minimist', () => {
 				return { task: 'task-to-run' };
 			} );
-			sandbox.stub( ckeditor5Dirs, 'getDevDirectories' ).returns( getDevDirectoriesResult );
+			sandbox.stub( workspace, 'getDevDirectories' ).returns( getDevDirectoriesResult );
 			mockery.registerMock( './functions/task-to-run', taskStub );
 			const tasks = require( '../../tasks/exec/tasks' )( config );
 
@@ -118,13 +116,13 @@ describe( 'exec-tasks', () => {
 		} );
 
 		it( 'should execute task over directories', () => {
-			const ckeditor5Dirs = require( '../../utils/ckeditor5-dirs' );
+			const { workspace } = require( 'ckeditor5-dev-utils' );
 			const taskStub = sinon.stub();
 
 			mockery.registerMock( 'minimist', () => {
 				return { task: 'task-to-run' };
 			} );
-			sandbox.stub( ckeditor5Dirs, 'getDevDirectories' ).returns( getDevDirectoriesResult );
+			sandbox.stub( workspace, 'getDevDirectories' ).returns( getDevDirectoriesResult );
 			mockery.registerMock( './functions/task-to-run', taskStub );
 			const tasks = require( '../../tasks/exec/tasks' )( config );
 
@@ -137,7 +135,7 @@ describe( 'exec-tasks', () => {
 
 		it( 'should execute task over specific directory', () => {
 			const Stream = require( 'stream' );
-			const ckeditor5Dirs = require( '../../utils/ckeditor5-dirs' );
+			const { workspace } = require( 'ckeditor5-dev-utils' );
 			const taskStub = sinon.stub().returns( new Stream() );
 
 			mockery.registerMock( 'minimist', () => {
@@ -146,7 +144,7 @@ describe( 'exec-tasks', () => {
 					repository: 'test1'
 				};
 			} );
-			sandbox.stub( ckeditor5Dirs, 'getDevDirectories' ).returns( getDevDirectoriesResult );
+			sandbox.stub( workspace, 'getDevDirectories' ).returns( getDevDirectoriesResult );
 			mockery.registerMock( './functions/task-to-run', taskStub );
 			const tasks = require( '../../tasks/exec/tasks' )( config );
 

+ 5 - 6
dev/tests/test/tasks.js

@@ -7,17 +7,16 @@
 
 'use strict';
 
-const tasks = require( '../../tasks/test/tasks' )();
-const buildUtils = require( '../../tasks/build/utils' );
-const devTools = require( '../../utils/tools' );
 const Vinyl = require( 'vinyl' );
+const tasks = require( '../../tasks/test/tasks' )();
+const { build, tools } = require( 'ckeditor5-dev-utils' );
 
 describe( 'test-node', () => {
 	describe( 'skipManual', () => {
 		it( 'should skip manual tests', ( done ) => {
 			const stream = tasks.skipManual();
 			const spy = sinon.spy();
-			const stub = sinon.stub( devTools, 'isFile', ( file ) => {
+			const stub = sinon.stub( tools, 'isFile', ( file ) => {
 				return file == 'file1.md';
 			} );
 			const unitTestFile = new Vinyl( {
@@ -31,7 +30,7 @@ describe( 'test-node', () => {
 				contents: null
 			} );
 
-			stream.pipe( buildUtils.noop( spy ) );
+			stream.pipe( build.noop( spy ) );
 
 			stream.once( 'finish', () => {
 				sinon.assert.calledOnce( spy );
@@ -61,7 +60,7 @@ describe( 'test-node', () => {
 				path: 'file1.js',
 				contents: new Buffer( '/* bender-tags: tag, browser-only */' )
 			} );
-			const noop = buildUtils.noop( spy );
+			const noop = build.noop( spy );
 			noop.once( 'finish', () => {
 				sinon.assert.calledOnce( spy );
 				sinon.assert.calledWithExactly( spy, unitTestFile );

+ 0 - 169
dev/tests/utils/ckeditor5-dirs.js

@@ -1,169 +0,0 @@
-/**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* global describe, it, beforeEach, afterEach */
-
-'use strict';
-
-const chai = require( 'chai' );
-const sinon = require( 'sinon' );
-const expect = chai.expect;
-const path = require( 'path' );
-const ckeditor5Dirs = require( '../../utils/ckeditor5-dirs' );
-const tools = require( '../../utils/tools' );
-const git = require( '../../utils/git' );
-let sandbox;
-
-describe( 'utils', () => {
-	beforeEach( () => {
-		sandbox = sinon.sandbox.create();
-	} );
-
-	afterEach( () => {
-		sandbox.restore();
-	} );
-
-	describe( 'ckeditor5dirs', () => {
-		describe( 'getDependencies', () => {
-			it( 'should be defined', () => expect( ckeditor5Dirs.getDependencies ).to.be.a( 'function' ) );
-
-			it( 'should return null if no CKEditor5 repository is found', () => {
-				const packageJSONDependencies = {
-					'plugin1': '',
-					'plugin2': '',
-					'plugin3': ''
-				};
-				expect( ckeditor5Dirs.getDependencies( packageJSONDependencies ) ).to.equal( null );
-				expect( ckeditor5Dirs.getDependencies() ).to.equal( null );
-			} );
-
-			it( 'should return only ckeditor5- dependencies', () => {
-				const packageJSONDependencies = {
-					'plugin1': '',
-					'ckeditor5-plugin-image': 'ckeditor/ckeditor5-plugin-image',
-					'plugin2': '',
-					'ckeditor5-core': 'ckeditor/ckeditor5-core'
-				};
-				const ckeditorDependencies = ckeditor5Dirs.getDependencies( packageJSONDependencies );
-
-				expect( ckeditorDependencies ).to.be.an( 'object' );
-				expect( ckeditorDependencies.plugin1 ).to.be.a( 'undefined' );
-				expect( ckeditorDependencies.plugin2 ).to.be.a( 'undefined' );
-				expect( ckeditorDependencies[ 'ckeditor5-plugin-image' ] ).to.be.a( 'string' );
-				expect( ckeditorDependencies[ 'ckeditor5-core' ] ).to.be.a( 'string' );
-			} );
-		} );
-
-		describe( 'getDirectories', () => {
-			it( 'should be defined', () => expect( ckeditor5Dirs.getDirectories ).to.be.a( 'function' ) );
-
-			it( 'should return only ckeditor5 directories', () => {
-				const workspacePath = '/workspace/path';
-				const sourceDirectories = [ 'tools', 'ckeditor5', 'ckeditor5-core', '.bin', 'ckeditor5-plugin-image' ];
-				sandbox.stub( tools, 'getDirectories', () => sourceDirectories );
-				const directories = ckeditor5Dirs.getDirectories( workspacePath );
-
-				expect( directories.length ).to.equal( 2 );
-				expect( directories[ 0 ] ).to.equal( 'ckeditor5-core' );
-				expect( directories[ 1 ] ).to.equal( 'ckeditor5-plugin-image' );
-			} );
-		} );
-
-		describe( 'getSymlinks', () => {
-			it( 'should return CKE5 symlinks from provided path', () => {
-				const fs = require( 'fs' );
-				const path = 'path/to/dir';
-				sandbox.stub( fs, 'readdirSync' ).returns( [ 'ckeditor5-core', 'ckeditor5-image', 'other-dependency' ] );
-				sandbox.stub( tools, 'isSymlink' ).returns( true );
-
-				const symlinks = ckeditor5Dirs.getSymlinks( path );
-				expect( symlinks.length ).to.equal( 2 );
-				expect( symlinks[ 0 ] ).to.equal( 'ckeditor5-core' );
-				expect( symlinks[ 1 ] ).to.equal( 'ckeditor5-image' );
-			} );
-		} );
-
-		describe( 'getDevDirectories', () => {
-			const packageJSONDependencies = {};
-			const workspacePath = '/workspace/path';
-			const ckeditor5Path = path.join( workspacePath, 'ckeditor5' );
-			const dependencies = {
-				'ckeditor5-plugin-image': 'ckeditor/ckeditor5-plugin-image',
-				'ckeditor5-core': 'ckeditor/ckeditor5-core'
-			};
-			const sourceDirectories = [ 'tools', 'ckeditor5', 'ckeditor5-core', '.bin', 'ckeditor5-plugin-image' ];
-			const repositoryInfo = { name: 'ckeditor5-core' };
-
-			it( 'should be defined', () => expect( ckeditor5Dirs.getDevDirectories ).to.be.a( 'function' ) );
-
-			it( 'should return empty array if no dev directories were found - because of missing ckeditor5-* repos', () => {
-				const wrongRepositoryInfo = { name: 'plugins/plugin' };
-
-				sandbox.stub( ckeditor5Dirs, 'getDirectories', () => sourceDirectories );
-				sandbox.stub( ckeditor5Dirs, 'getDependencies', () => dependencies );
-				sandbox.stub( git, 'parseRepositoryUrl' ).returns( wrongRepositoryInfo );
-
-				const directories = ckeditor5Dirs.getDevDirectories( workspacePath, packageJSONDependencies, ckeditor5Path );
-
-				expect( directories ).to.be.a( 'array' );
-				expect( directories.length ).to.equal( 0 );
-			} );
-
-			it( 'should return empty array if no dev directories were found - because of missing ckeditor5-* dirs', () => {
-				const wrongDirectories = [ 'tools', 'ckeditor5', '.bin' ];
-
-				sandbox.stub( ckeditor5Dirs, 'getDirectories', () => wrongDirectories );
-				sandbox.stub( ckeditor5Dirs, 'getDependencies', () => dependencies );
-				sandbox.stub( git, 'parseRepositoryUrl' ).returns( repositoryInfo );
-
-				const directories = ckeditor5Dirs.getDevDirectories( workspacePath, packageJSONDependencies, ckeditor5Path );
-
-				expect( directories ).to.be.a( 'array' );
-				expect( directories.length ).to.equal( 0 );
-			} );
-
-			it( 'should return only ckeditor5 directories in development mode', () => {
-				sandbox.stub( ckeditor5Dirs, 'getDirectories', () => sourceDirectories );
-				sandbox.stub( ckeditor5Dirs, 'getDependencies', () => dependencies );
-				sandbox.stub( git, 'parseRepositoryUrl' ).returns( repositoryInfo );
-
-				const directories = ckeditor5Dirs.getDevDirectories( workspacePath, packageJSONDependencies, ckeditor5Path );
-
-				expect( directories.length ).to.equal( 2 );
-				expect( directories[ 0 ] ).to.deep.equal( {
-						repositoryURL: 'ckeditor/ckeditor5-plugin-image',
-						repositoryPath: '/workspace/path/ckeditor5/node_modules/ckeditor5-plugin-image'
-					} );
-				expect( directories[ 1 ] ).to.deep.equal( {
-						repositoryURL: 'ckeditor/ckeditor5-core',
-						repositoryPath: '/workspace/path/ckeditor5/node_modules/ckeditor5-core'
-					} );
-			} );
-
-			it( 'should return only ckeditor5 directories in development mode, including root directory', () => {
-				sandbox.stub( ckeditor5Dirs, 'getDirectories', () => sourceDirectories );
-				sandbox.stub( ckeditor5Dirs, 'getDependencies', () => dependencies );
-				sandbox.stub( git, 'parseRepositoryUrl' ).returns( repositoryInfo );
-				const includeRoot = true;
-
-				const directories = ckeditor5Dirs.getDevDirectories( workspacePath, packageJSONDependencies, ckeditor5Path, includeRoot );
-
-				expect( directories.length ).to.equal( 3 );
-				expect( directories[ 0 ] ).to.deep.equal( {
-						repositoryURL: 'ckeditor/ckeditor5',
-						repositoryPath: '/workspace/path/ckeditor5'
-					} );
-				expect( directories[ 1 ] ).to.deep.equal( {
-						repositoryURL: 'ckeditor/ckeditor5-plugin-image',
-						repositoryPath: '/workspace/path/ckeditor5/node_modules/ckeditor5-plugin-image'
-					} );
-				expect( directories[ 2 ] ).to.deep.equal( {
-						repositoryURL: 'ckeditor/ckeditor5-core',
-						repositoryPath: '/workspace/path/ckeditor5/node_modules/ckeditor5-core'
-					} );
-			} );
-		} );
-	} );
-} );

+ 0 - 266
dev/tests/utils/git.js

@@ -1,266 +0,0 @@
-/**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* global describe, it, beforeEach, afterEach */
-
-'use strict';
-
-let sandbox;
-const git = require( '../../utils/git' );
-const chai = require( 'chai' );
-const sinon = require( 'sinon' );
-const tools = require( '../../utils/tools' );
-const expect = chai.expect;
-
-describe( 'utils', () => {
-	beforeEach( () => {
-		sandbox = sinon.sandbox.create();
-	} );
-
-	afterEach( () => {
-		sandbox.restore();
-	} );
-
-	describe( 'git', () => {
-		describe( 'parseRepositoryUrl', () => {
-			it( 'should be defined', () => expect( git.parseRepositoryUrl ).to.be.a( 'function' ) );
-
-			it( 'should parse short GitHub URL ', () => {
-				const urlInfo = git.parseRepositoryUrl( 'ckeditor/ckeditor5-core' );
-
-				expect( urlInfo.server ).to.equal( 'git@github.com:' );
-				expect( urlInfo.repository ).to.equal( 'ckeditor/ckeditor5-core' );
-				expect( urlInfo.user ).to.equal( 'ckeditor' );
-				expect( urlInfo.name ).to.equal( 'ckeditor5-core' );
-				expect( urlInfo.branch ).to.equal( 'master' );
-			} );
-
-			it( 'should parse short GitHub URL with provided branch ', () => {
-				const urlInfo = git.parseRepositoryUrl( 'ckeditor/ckeditor5-core#experimental' );
-
-				expect( urlInfo.server ).to.equal( 'git@github.com:' );
-				expect( urlInfo.repository ).to.equal( 'ckeditor/ckeditor5-core' );
-				expect( urlInfo.user ).to.equal( 'ckeditor' );
-				expect( urlInfo.name ).to.equal( 'ckeditor5-core' );
-				expect( urlInfo.branch ).to.equal( 'experimental' );
-			} );
-
-			it( 'should parse full GitHub URL (http)', () => {
-				const urlInfo = git.parseRepositoryUrl( 'http://github.com/ckeditor/ckeditor5-core.git' );
-
-				expect( urlInfo.server ).to.equal( 'http://github.com/' );
-				expect( urlInfo.repository ).to.equal( 'ckeditor/ckeditor5-core.git' );
-				expect( urlInfo.user ).to.equal( 'ckeditor' );
-				expect( urlInfo.name ).to.equal( 'ckeditor5-core' );
-				expect( urlInfo.branch ).to.equal( 'master' );
-			} );
-
-			it( 'should parse full GitHub URL (http) with provided branch', () => {
-				const urlInfo = git.parseRepositoryUrl( 'http://github.com/ckeditor/ckeditor5-core.git#experimental' );
-
-				expect( urlInfo.server ).to.equal( 'http://github.com/' );
-				expect( urlInfo.repository ).to.equal( 'ckeditor/ckeditor5-core.git' );
-				expect( urlInfo.user ).to.equal( 'ckeditor' );
-				expect( urlInfo.name ).to.equal( 'ckeditor5-core' );
-				expect( urlInfo.branch ).to.equal( 'experimental' );
-			} );
-
-			it( 'should parse full GitHub URL (https)', () => {
-				const urlInfo = git.parseRepositoryUrl( 'https://github.com/ckeditor/ckeditor5-core.git' );
-
-				expect( urlInfo.server ).to.equal( 'https://github.com/' );
-				expect( urlInfo.repository ).to.equal( 'ckeditor/ckeditor5-core.git' );
-				expect( urlInfo.user ).to.equal( 'ckeditor' );
-				expect( urlInfo.name ).to.equal( 'ckeditor5-core' );
-				expect( urlInfo.branch ).to.equal( 'master' );
-			} );
-
-			it( 'should parse full GitHub URL (https) with provided branch', () => {
-				const urlInfo = git.parseRepositoryUrl( 'https://github.com/ckeditor/ckeditor5-core.git#t/122' );
-
-				expect( urlInfo.server ).to.equal( 'https://github.com/' );
-				expect( urlInfo.repository ).to.equal( 'ckeditor/ckeditor5-core.git' );
-				expect( urlInfo.user ).to.equal( 'ckeditor' );
-				expect( urlInfo.name ).to.equal( 'ckeditor5-core' );
-				expect( urlInfo.branch ).to.equal( 't/122' );
-			} );
-
-			it( 'should parse full GitHub URL (git)', () => {
-				const urlInfo = git.parseRepositoryUrl( 'git@github.com:ckeditor/ckeditor5-core.git' );
-
-				expect( urlInfo.server ).to.equal( 'git@github.com:' );
-				expect( urlInfo.repository ).to.equal( 'ckeditor/ckeditor5-core.git' );
-				expect( urlInfo.user ).to.equal( 'ckeditor' );
-				expect( urlInfo.name ).to.equal( 'ckeditor5-core' );
-				expect( urlInfo.branch ).to.equal( 'master' );
-			} );
-
-			it( 'should parse full GitHub URL (git)', () => {
-				const urlInfo = git.parseRepositoryUrl( 'git://github.com/ckeditor/ckeditor5-core.git' );
-
-				expect( urlInfo.server ).to.equal( 'git://github.com/' );
-				expect( urlInfo.repository ).to.equal( 'ckeditor/ckeditor5-core.git' );
-				expect( urlInfo.user ).to.equal( 'ckeditor' );
-				expect( urlInfo.name ).to.equal( 'ckeditor5-core' );
-				expect( urlInfo.branch ).to.equal( 'master' );
-			} );
-
-			it( 'should parse full GitHub URL (git) with provided branch', () => {
-				const urlInfo = git.parseRepositoryUrl( 'git@github.com:ckeditor/ckeditor5-core.git#new-feature' );
-
-				expect( urlInfo.server ).to.equal( 'git@github.com:' );
-				expect( urlInfo.repository ).to.equal( 'ckeditor/ckeditor5-core.git' );
-				expect( urlInfo.user ).to.equal( 'ckeditor' );
-				expect( urlInfo.name ).to.equal( 'ckeditor5-core' );
-				expect( urlInfo.branch ).to.equal( 'new-feature' );
-			} );
-
-			it( 'should return null if GitHub URL is not valid', () => {
-				let urlInfo = git.parseRepositoryUrl( 'https://ckeditor.com' );
-				expect( urlInfo ).to.equal( null );
-
-				urlInfo = git.parseRepositoryUrl( 'https://github.com/info.html' );
-				expect( urlInfo ).to.equal( null );
-			} );
-		} );
-
-		describe( 'cloneRepository', () => {
-			it( 'should be defined', () => expect( git.cloneRepository ).to.be.a( 'function' ) );
-
-			it( 'should call clone commands', () => {
-				const shExecStub = sandbox.stub( tools, 'shExec' );
-				const workspacePath = '/path/to/workspace/';
-				const urlInfo = git.parseRepositoryUrl( 'git@github.com:ckeditor/ckeditor5-core#new-feature' );
-				const cloneCommands = `cd ${ workspacePath } && git clone ${ urlInfo.server + urlInfo.repository }`;
-
-				git.cloneRepository( urlInfo, workspacePath );
-
-				expect( shExecStub.calledOnce ).to.equal( true );
-				expect( shExecStub.firstCall.args[ 0 ] ).to.equal( cloneCommands );
-			} );
-		} );
-
-		describe( 'checkout', () => {
-			it( 'should be defined', () => expect( git.checkout ).to.be.a( 'function' ) );
-
-			it( 'should call checkout commands', () => {
-				const shExecStub = sandbox.stub( tools, 'shExec' );
-				const repositoryLocation = 'path/to/repository';
-				const branchName = 'branch-to-checkout';
-				const checkoutCommands = [
-					`cd ${ repositoryLocation }`,
-					`git checkout ${ branchName }`
-				].join( ' && ' );
-
-				git.checkout( repositoryLocation, branchName );
-
-				expect( shExecStub.calledOnce ).to.equal( true );
-				expect( shExecStub.firstCall.args[ 0 ] ).to.equal( checkoutCommands );
-			} );
-		} );
-
-		describe( 'pull', () => {
-			it( 'should be defined', () => expect( git.pull ).to.be.a( 'function' ) );
-
-			it( 'should call pull commands', () => {
-				const shExecStub = sandbox.stub( tools, 'shExec' );
-				const repositoryLocation = 'path/to/repository';
-				const branchName = 'branch-to-pull';
-				const pullCommands = `cd ${ repositoryLocation } && git pull origin ${ branchName }`;
-
-				git.pull( repositoryLocation, branchName );
-
-				expect( shExecStub.calledOnce ).to.equal( true );
-				expect( shExecStub.firstCall.args[ 0 ] ).to.equal( pullCommands );
-			} );
-		} );
-
-		describe( 'fetchAll', () => {
-			it( 'should be defined', () => expect( git.fetchAll ).to.be.a( 'function' ) );
-
-			it( 'should call fetch commands', () => {
-				const shExecStub = sandbox.stub( tools, 'shExec' );
-				const repositoryLocation = 'path/to/repository';
-				const fetchCommands = `cd ${ repositoryLocation } && git fetch --all`;
-
-				git.fetchAll( repositoryLocation );
-
-				expect( shExecStub.calledOnce ).to.be.equal( true );
-				expect( shExecStub.firstCall.args[ 0 ] ).to.be.equal( fetchCommands );
-			} );
-		} );
-
-		describe( 'initializeRepository', () => {
-			it( 'should be defined', () => expect( git.initializeRepository ).to.be.a( 'function' ) );
-
-			it( 'should call initialize commands', () => {
-				const shExecStub = sandbox.stub( tools, 'shExec' );
-				const repositoryLocation = 'path/to/repository';
-				const initializeCommands = [
-					`git init ${ repositoryLocation }`
-				];
-
-				git.initializeRepository( repositoryLocation );
-
-				expect( shExecStub.calledOnce ).to.equal( true );
-				expect( shExecStub.firstCall.args[ 0 ] ).to.equal( initializeCommands.join( ' && ' ) );
-			} );
-		} );
-
-		describe( 'getStatus', () => {
-			it( 'should be defined', () => expect( git.getStatus ).to.be.a( 'function' ) );
-
-			it( 'should call status command', () => {
-				const shExecStub = sandbox.stub( tools, 'shExec' );
-				const repositoryLocation = 'path/to/repository';
-				const statusCommands = `cd ${ repositoryLocation } && git status --porcelain -sb`;
-
-				git.getStatus( repositoryLocation );
-
-				expect( shExecStub.calledOnce ).to.equal( true );
-				expect( shExecStub.firstCall.args[ 0 ] ).to.equal( statusCommands );
-			} );
-		} );
-
-		describe( 'initialCommit', () => {
-			it( 'should be defined', () => expect( git.initialCommit ).to.be.a( 'function' ) );
-
-			it( 'should execute commit commands', () => {
-				const shExecStub = sandbox.stub( tools, 'shExec' );
-				const pluginName = 'ckeditor5-plugin-name';
-				const repositoryPath = '/path/to/repo';
-				const commitCommands = [
-					`cd ${ repositoryPath }`,
-					`git add .`,
-					`git commit -m "Initial commit for ${ pluginName }."`
-				];
-
-				git.initialCommit( pluginName, repositoryPath );
-
-				expect( shExecStub.calledOnce ).to.equal( true );
-				expect( shExecStub.firstCall.args[ 0 ] ).to.equal( commitCommands.join( ' && ' ) );
-			} );
-		} );
-
-		describe( 'addRemote', () => {
-			it( 'should be defined', () => expect( git.addRemote ).to.be.a( 'function' ) );
-
-			it( 'should execute add remote commands', () => {
-				const shExecStub = sandbox.stub( tools, 'shExec' );
-				const gitHubPath = 'ckeditor5/ckeditor5-plugin-name';
-				const repositoryPath = '/path/to/repo';
-				const addRemoteCommands = [
-					`cd ${ repositoryPath }`,
-					`git remote add origin git@github.com:${ gitHubPath }.git`
-				];
-
-				git.addRemote( repositoryPath, gitHubPath );
-
-				expect( shExecStub.calledOnce ).to.equal( true );
-				expect( shExecStub.firstCall.args[ 0 ] ).to.equal( addRemoteCommands.join( ' && ' ) );
-			} );
-		} );
-	} );
-} );

+ 0 - 26
dev/tests/utils/log.js

@@ -1,26 +0,0 @@
-/**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* global describe, it */
-
-'use strict';
-
-const sinon = require( 'sinon' );
-const log = require( '../../utils/log' );
-
-describe( 'log', () => {
-	it( 'should log using configured functions', () => {
-		const outFn = sinon.spy();
-		const errFn = sinon.spy();
-
-		log.configure( outFn, errFn );
-
-		log.out( 'output' );
-		log.err( 'error' );
-
-		sinon.assert.calledWithExactly( outFn, 'output' );
-		sinon.assert.calledWithExactly( errFn, 'error' );
-	} );
-} );

+ 0 - 469
dev/tests/utils/tools.js

@@ -1,469 +0,0 @@
-/**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* global describe, it, beforeEach, afterEach */
-
-'use strict';
-
-const chai = require( 'chai' );
-const sinon = require( 'sinon' );
-const expect = chai.expect;
-const tools = require( '../../utils/tools' );
-const path = require( 'path' );
-const fs = require( 'fs' );
-let sandbox;
-
-describe( 'utils', () => {
-	beforeEach( () => {
-		sandbox = sinon.sandbox.create();
-	} );
-
-	afterEach( () => {
-		sandbox.restore();
-	} );
-
-	describe( 'tools', () => {
-		describe( 'shExec', () => {
-			it( 'should be defined', () => expect( tools.shExec ).to.be.a( 'function' ) );
-
-			it( 'should execute command', () => {
-				const sh = require( 'shelljs' );
-				const execStub = sandbox.stub( sh, 'exec' ).returns( { code: 0 } );
-
-				tools.shExec( 'command' );
-
-				sinon.assert.calledOnce( execStub );
-			} );
-
-			it( 'should throw error on unsuccessful call', () => {
-				const sh = require( 'shelljs' );
-				const execStub = sandbox.stub( sh, 'exec' ).returns( { code: 1 } );
-
-				expect( () => {
-					tools.shExec( 'command' );
-				} ).to.throw();
-				sinon.assert.calledOnce( execStub );
-			} );
-
-			it( 'should output using log functions', () => {
-				const sh = require( 'shelljs' );
-				const execStub = sandbox.stub( sh, 'exec' ).returns( { code: 0, stdout: 'out', stderr: 'err' } );
-
-				sandbox.stub( console, 'log' );
-
-				tools.shExec( 'command' );
-
-				sinon.assert.calledOnce( execStub );
-				sinon.assert.calledTwice( console.log );
-			} );
-
-			it( 'should not log when in silent mode', () => {
-				const sh = require( 'shelljs' );
-				const execStub = sandbox.stub( sh, 'exec' ).returns( { code: 0, stdout: 'out', stderr: 'err' } );
-				const log = require( '../../utils/log' );
-				const outFn = sandbox.spy();
-				const errFn = sandbox.spy();
-				log.configure( outFn, errFn );
-
-				tools.shExec( 'command', false );
-
-				sinon.assert.calledOnce( execStub );
-				sinon.assert.notCalled( outFn );
-				sinon.assert.notCalled( errFn );
-			} );
-
-			it( 'should not log if no output from executed command', () => {
-				const sh = require( 'shelljs' );
-				const execStub = sandbox.stub( sh, 'exec' ).returns( { code: 0, stdout: '', stderr: '' } );
-				const log = require( '../../utils/log' );
-				const outFn = sandbox.spy();
-				const errFn = sandbox.spy();
-				log.configure( outFn, errFn );
-
-				tools.shExec( 'command' );
-
-				sinon.assert.calledOnce( execStub );
-				sinon.assert.notCalled( outFn );
-				sinon.assert.notCalled( errFn );
-			} );
-		} );
-
-		describe( 'linkDirectories', () => {
-			it( 'should be defined', () => expect( tools.linkDirectories ).to.be.a( 'function' ) );
-
-			it( 'should link directories', () => {
-				const isSymlinkStub = sandbox.stub( tools, 'isSymlink' ).returns( false );
-				const isDirectoryStub = sandbox.stub( tools, 'isDirectory' ).returns( false );
-				const symlinkStub = sandbox.stub( fs, 'symlinkSync' );
-				const source = '/source/dir';
-				const destination = '/destination/dir';
-
-				tools.linkDirectories( source, destination );
-
-				expect( isDirectoryStub.calledOnce ).to.equal( true );
-				expect( isSymlinkStub.calledOnce ).to.equal( true );
-				expect( symlinkStub.calledOnce ).to.equal( true );
-				expect( symlinkStub.firstCall.args[ 0 ] ).to.equal( source );
-				expect( symlinkStub.firstCall.args[ 1 ] ).to.equal( destination );
-			} );
-
-			it( 'should remove destination directory before linking', () => {
-				const shExecStub = sandbox.stub( tools, 'shExec' );
-				const isSymlinkStub = sandbox.stub( tools, 'isSymlink' ).returns( false );
-				const isDirectoryStub = sandbox.stub( tools, 'isDirectory' ).returns( true );
-				const symlinkStub = sandbox.stub( fs, 'symlinkSync' );
-				const source = '/source/dir';
-				const destination = '/destination/dir';
-
-				tools.linkDirectories( source, destination );
-
-				expect( isDirectoryStub.calledOnce ).to.equal( true );
-				expect( isSymlinkStub.calledOnce ).to.equal( true );
-				expect( shExecStub.calledOnce ).to.equal( true );
-				expect( symlinkStub.firstCall.args[ 0 ] ).to.equal( source );
-				expect( symlinkStub.firstCall.args[ 1 ] ).to.equal( destination );
-			} );
-
-			it( 'should unlink destination directory if symlink', () => {
-				const shExecStub = sandbox.stub( tools, 'shExec' );
-				const isSymlinkStub = sandbox.stub( tools, 'isSymlink' ).returns( true );
-				const removeSymlinkStub = sandbox.stub( tools, 'removeSymlink' );
-				const isDirectoryStub = sandbox.stub( tools, 'isDirectory' ).returns( true );
-				const symlinkStub = sandbox.stub( fs, 'symlinkSync' );
-				const source = '/source/dir';
-				const destination = '/destination/dir';
-
-				tools.linkDirectories( source, destination );
-
-				expect( isDirectoryStub.notCalled ).to.equal( true );
-				expect( isSymlinkStub.calledOnce ).to.equal( true );
-				expect( shExecStub.notCalled ).to.equal( true );
-				expect( removeSymlinkStub.calledOnce ).to.equal( true );
-				expect( removeSymlinkStub.firstCall.args[ 0 ] ).to.equal( destination );
-				expect( symlinkStub.firstCall.args[ 0 ] ).to.equal( source );
-				expect( symlinkStub.firstCall.args[ 1 ] ).to.equal( destination );
-			} );
-		} );
-
-		describe( 'getDirectories', () => {
-			it( 'should be defined', () => expect( tools.getDirectories ).to.be.a( 'function' ) );
-
-			it( 'should get directories in specified path', () => {
-				const fs = require( 'fs' );
-				const directories = [ 'dir1', 'dir2', 'dir3' ];
-				const readdirSyncStub = sandbox.stub( fs, 'readdirSync', () => directories );
-				const isDirectoryStub = sandbox.stub( tools, 'isDirectory' ).returns( true );
-				const dirPath = 'path';
-
-				tools.getDirectories( dirPath );
-
-				expect( readdirSyncStub.calledOnce ).to.equal( true );
-				expect( isDirectoryStub.calledThrice ).to.equal( true );
-				expect( isDirectoryStub.firstCall.args[ 0 ] ).to.equal( path.join( dirPath, directories[ 0 ] ) );
-				expect( isDirectoryStub.secondCall.args[ 0 ] ).to.equal( path.join( dirPath, directories[ 1 ] ) );
-				expect( isDirectoryStub.thirdCall.args[ 0 ] ).to.equal( path.join( dirPath, directories[ 2 ] ) );
-			} );
-		} );
-
-		describe( 'isDirectory', () => {
-			it( 'should be defined', () => expect( tools.isDirectory ).to.be.a( 'function' ) );
-
-			it( 'should return true if path points to directory', () => {
-				const fs = require( 'fs' );
-				const statSyncStub = sandbox.stub( fs, 'statSync', () => ( { isDirectory: () => true } ) );
-				const path = 'path';
-
-				const result = tools.isDirectory( path );
-
-				expect( statSyncStub.calledOnce ).to.equal( true );
-				expect( statSyncStub.firstCall.args[ 0 ] ).to.equal( path );
-				expect( result ).to.equal( true );
-			} );
-
-			it( 'should return false if path does not point to directory', () => {
-				const fs = require( 'fs' );
-				const statSyncStub = sandbox.stub( fs, 'statSync', () => ( { isDirectory: () => false } ) );
-				const path = 'path';
-
-				const result = tools.isDirectory( path );
-
-				expect( statSyncStub.calledOnce ).to.equal( true );
-				expect( statSyncStub.firstCall.args[ 0 ] ).to.equal( path );
-				expect( result ).to.equal( false );
-			} );
-
-			it( 'should return false if statSync method throws', () => {
-				const fs = require( 'fs' );
-				const statSyncStub = sandbox.stub( fs, 'statSync' ).throws();
-				const path = 'path';
-
-				const result = tools.isDirectory( path );
-
-				expect( statSyncStub.calledOnce ).to.equal( true );
-				expect( statSyncStub.firstCall.args[ 0 ] ).to.equal( path );
-				expect( result ).to.equal( false );
-			} );
-		} );
-
-		describe( 'isFile', () => {
-			it( 'should be defined', () => expect( tools.isFile ).to.be.a( 'function' ) );
-
-			it( 'should return true if path points to file', () => {
-				const fs = require( 'fs' );
-				const statSyncStub = sandbox.stub( fs, 'statSync', () => ( { isFile: () => true } ) );
-				const path = 'path';
-
-				const result = tools.isFile( path );
-
-				expect( statSyncStub.calledOnce ).to.equal( true );
-				expect( statSyncStub.firstCall.args[ 0 ] ).to.equal( path );
-				expect( result ).to.equal( true );
-			} );
-
-			it( 'should return false if path does not point to directory', () => {
-				const fs = require( 'fs' );
-				const statSyncStub = sandbox.stub( fs, 'statSync', () => ( { isFile: () => false } ) );
-				const path = 'path';
-
-				const result = tools.isFile( path );
-
-				expect( statSyncStub.calledOnce ).to.equal( true );
-				expect( statSyncStub.firstCall.args[ 0 ] ).to.equal( path );
-				expect( result ).to.equal( false );
-			} );
-
-			it( 'should return false if statSync method throws', () => {
-				const fs = require( 'fs' );
-				const statSyncStub = sandbox.stub( fs, 'statSync' ).throws();
-				const path = 'path';
-
-				const result = tools.isFile( path );
-
-				expect( statSyncStub.calledOnce ).to.equal( true );
-				expect( statSyncStub.firstCall.args[ 0 ] ).to.equal( path );
-				expect( result ).to.equal( false );
-			} );
-		} );
-
-		describe( 'isSymlink', () => {
-			it( 'should return true if path points to symbolic link', () => {
-				const path = 'path/to/file';
-				const fs = require( 'fs' );
-				sandbox.stub( fs, 'lstatSync' ).returns( {
-					isSymbolicLink: () => true
-				} );
-
-				expect( tools.isSymlink( path ) ).to.equal( true );
-			} );
-
-			it( 'should return false if lstatSync throws', () => {
-				const path = 'path/to/file';
-				const fs = require( 'fs' );
-				sandbox.stub( fs, 'lstatSync' ).throws();
-
-				expect( tools.isSymlink( path ) ).to.equal( false );
-			} );
-		} );
-
-		describe( 'updateJSONFile', () => {
-			it( 'should be defined', () => expect( tools.updateJSONFile ).to.be.a( 'function' ) );
-			it( 'should read, update and save JSON file', () => {
-				const path = 'path/to/file.json';
-				const fs = require( 'fs' );
-				const readFileStub = sandbox.stub( fs, 'readFileSync', () => '{}' );
-				const modifiedJSON = { modified: true };
-				const writeFileStub = sandbox.stub( fs, 'writeFileSync' );
-
-				tools.updateJSONFile( path, () => {
-					return modifiedJSON;
-				} );
-
-				expect( readFileStub.calledOnce ).to.equal( true );
-				expect( readFileStub.firstCall.args[ 0 ] ).to.equal( path );
-				expect( writeFileStub.calledOnce ).to.equal( true );
-				expect( writeFileStub.firstCall.args[ 0 ] ).to.equal( path );
-				expect( writeFileStub.firstCall.args[ 1 ] ).to.equal( JSON.stringify( modifiedJSON, null, 2 ) + '\n' );
-			} );
-		} );
-
-		describe( 'sortObject', () => {
-			it( 'should be defined', () => expect( tools.sortObject ).to.be.a( 'function' ) );
-			it( 'should reinsert object properties in alphabetical order', () => {
-				let obj = {
-					c: '', d: '', a: '', z: ''
-				};
-
-				const sorted = {
-					a: '', c: '', d: '', z: ''
-				};
-
-				obj = tools.sortObject( obj );
-
-				expect( JSON.stringify( obj ) ).to.equal( JSON.stringify( sorted ) );
-			} );
-		} );
-
-		describe( 'readPackageName', () => {
-			const modulePath = 'path/to/module';
-			it( 'should read package name from NPM module', () => {
-				sandbox.stub( tools, 'isFile' ).returns( true );
-				const fs = require( 'fs' );
-				const name = 'module-name';
-				sandbox.stub( fs, 'readFileSync' ).returns( JSON.stringify( { name: name } ) );
-
-				const result = tools.readPackageName( modulePath );
-
-				expect( result ).to.equal( name );
-			} );
-
-			it( 'should return null if no package.json is found', () => {
-				sandbox.stub( tools, 'isFile' ).returns( false );
-
-				const result = tools.readPackageName( modulePath );
-
-				expect( result ).to.equal( null );
-			} );
-
-			it( 'should return null if no name in package.json is provided', () => {
-				sandbox.stub( tools, 'isFile' ).returns( true );
-				const fs = require( 'fs' );
-				sandbox.stub( fs, 'readFileSync' ).returns( JSON.stringify( { } ) );
-
-				const result = tools.readPackageName( modulePath );
-
-				expect( result ).to.equal( null );
-			} );
-		} );
-
-		describe( 'npmInstall', () => {
-			it( 'should be defined', () => expect( tools.npmInstall ).to.be.a( 'function' ) );
-			it( 'should execute npm install command', () => {
-				const shExecStub = sandbox.stub( tools, 'shExec' );
-				const path = '/path/to/repository';
-
-				tools.npmInstall( path );
-
-				expect( shExecStub.calledOnce ).to.equal( true );
-				expect( shExecStub.firstCall.args[ 0 ] ).to.equal( `cd ${ path } && npm install` );
-			} );
-		} );
-
-		describe( 'npmUpdate', () => {
-			it( 'should be defined', () => expect( tools.npmUpdate ).to.be.a( 'function' ) );
-			it( 'should execute npm update command', () => {
-				const shExecStub = sandbox.stub( tools, 'shExec' );
-				const path = '/path/to/repository';
-
-				tools.npmUpdate( path );
-
-				expect( shExecStub.calledOnce ).to.equal( true );
-				expect( shExecStub.firstCall.args[ 0 ] ).to.equal( `cd ${ path } && npm update --dev` );
-			} );
-		} );
-
-		describe( 'npmUninstall', () => {
-			it( 'should be defined', () => expect( tools.npmUninstall ).to.be.a( 'function' ) );
-			it( 'should execute npm uninstall command', () => {
-				const shExecStub = sandbox.stub( tools, 'shExec' );
-				const path = '/path/to/repository';
-				const moduleName = 'module-name';
-
-				tools.npmUninstall( path, moduleName );
-
-				expect( shExecStub.calledOnce ).to.equal( true );
-				expect( shExecStub.firstCall.args[ 0 ] ).to.equal( `cd ${ path } && npm uninstall ${ moduleName }` );
-			} );
-		} );
-
-		describe( 'copyTemplateFiles', () => {
-			it( 'should be defined', () => expect( tools.copyTemplateFiles ).to.be.a( 'function' ) );
-			it( 'should copy files and replace provided texts', () => {
-				const path = require( 'path' );
-				const fs = require( 'fs-extra' );
-
-				const readFileStub = sandbox.stub( fs, 'readFileSync' );
-				readFileStub.onFirstCall().returns( 'file data {{var1}}, {{var2}}' );
-				readFileStub.onSecondCall().returns( '{{var1}}, {{var2}}, {{var2}}{{var1}}' );
-
-				const writeFileStub = sandbox.stub( fs, 'writeFileSync' );
-				const ensureDirStub = sandbox.stub( fs, 'ensureDirSync' );
-				const sources = [ '/path/to/file1.md', '/path/to/file2.md' ];
-				const destination = '/destination/path';
-
-				tools.copyTemplateFiles( sources, destination, {
-					'{{var1}}': 'foo',
-					'{{var2}}': 'bar'
-				} );
-
-				sinon.assert.calledWithExactly( ensureDirStub, destination );
-				sinon.assert.calledTwice( readFileStub );
-				sinon.assert.calledWithExactly( readFileStub.firstCall, sources[ 0 ], 'utf8' );
-				sinon.assert.calledWithExactly( readFileStub.secondCall, sources[ 1 ], 'utf8' );
-				sinon.assert.calledTwice( writeFileStub );
-				let savePath = path.join( destination, path.basename( sources[ 0 ] ) );
-				sinon.assert.calledWithExactly( writeFileStub.firstCall, savePath, 'file data foo, bar', 'utf8' );
-				savePath = path.join( destination, path.basename( sources[ 1 ] ) );
-				sinon.assert.calledWithExactly( writeFileStub.secondCall, savePath, 'foo, bar, barfoo', 'utf8' );
-			} );
-		} );
-
-		describe( 'getGitUrlFromNpm', () => {
-			const repository = {
-				type: 'git',
-				url: 'git@github.com:ckeditor/ckeditor5-core'
-			};
-			const moduleName = 'ckeditor5-core';
-
-			it( 'should be defined', () => expect( tools.getGitUrlFromNpm ).to.be.a( 'function' ) );
-			it( 'should call npm view command', () => {
-				const shExecStub = sandbox.stub( tools, 'shExec', () => {
-					return JSON.stringify( repository );
-				} );
-				const url = tools.getGitUrlFromNpm( moduleName );
-
-				expect( shExecStub.calledOnce ).to.equal( true );
-				expect( shExecStub.firstCall.args[ 0 ] ).to.equal( `npm view ${ moduleName } repository --json` );
-				expect( url ).to.equal( repository.url );
-			} );
-
-			it( 'should return null if module is not found', () => {
-				sandbox.stub( tools, 'shExec' ).throws( new Error( 'npm ERR! code E404' ) );
-				const url = tools.getGitUrlFromNpm( moduleName );
-				expect( url ).to.equal( null );
-			} );
-
-			it( 'should return null if module has no repository information', () => {
-				sandbox.stub( tools, 'shExec' ).returns( JSON.stringify( {} ) );
-				const url = tools.getGitUrlFromNpm( moduleName );
-				expect( url ).to.equal( null );
-			} );
-
-			it( 'should throw on other errors', () => {
-				const error = new Error( 'Random error.' );
-				sandbox.stub( tools, 'shExec' ).throws( error );
-				const getUrlSpy = sandbox.spy( tools, 'getGitUrlFromNpm' );
-
-				try {
-					tools.getGitUrlFromNpm( moduleName );
-				} catch ( e ) {}
-
-				expect( getUrlSpy.threw( error ) ).to.equal( true );
-			} );
-		} );
-
-		describe( 'removeSymlink', () => {
-			it( 'should unlink provided symlink', () => {
-				const fs = require( 'fs' );
-				const unlinkStub = sandbox.stub( fs, 'unlinkSync' );
-				const path = 'path/to/symlink';
-
-				tools.removeSymlink( path );
-
-				expect( unlinkStub.calledOnce ).to.equal( true );
-				expect( unlinkStub.firstCall.args[ 0 ] ).to.equal( path );
-			} );
-		} );
-	} );
-} );

+ 0 - 108
dev/utils/ckeditor5-dirs.js

@@ -1,108 +0,0 @@
-/**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-const path = require( 'path' );
-const tools = require( './tools' );
-const git = require( './git' );
-
-const dependencyRegExp = /^ckeditor5-/;
-
-module.exports = {
-	/**
-	 * Returns dependencies that starts with `ckeditor5-`, and have valid, short GitHub url. Returns `null` if no
-	 * dependencies are found.
-	 *
-	 * @param {Object} dependencies Dependencies object loaded from `package.json` file.
-	 * @returns {Object|null}
-	 */
-	getDependencies( dependencies ) {
-		let result = null;
-
-		if ( dependencies ) {
-			Object.keys( dependencies ).forEach( ( key ) => {
-				if ( dependencyRegExp.test( key ) ) {
-					if ( result === null ) {
-						result = {};
-					}
-
-					result[ key ] = dependencies[ key ];
-				}
-			} );
-		}
-
-		return result;
-	},
-
-	/**
-	 * Returns all directories under specified path that match `ckeditor5-*` pattern.
-	 *
-	 * @param {String} path
-	 * @returns {Array.<String>}
-	 */
-	getDirectories( path ) {
-		return tools.getDirectories( path ).filter( dir => {
-			return dependencyRegExp.test( dir );
-		} );
-	},
-
-	/**
-	 * Returns a list of symbolic links to directories with names starting with `ckeditor5-` prefix.
-	 *
-	 * @param {String} path Path to directory,
-	 * @returns {Array} Array with directories names.
-	 */
-	getSymlinks( path ) {
-		const fs = require( 'fs' );
-		const pth = require( 'path' );
-
-		return fs.readdirSync( path ).filter( item => {
-			const fullPath = pth.join( path, item );
-
-			return dependencyRegExp.test( item ) && tools.isSymlink( fullPath );
-		} );
-	},
-
-	/**
-	 * Returns an array with information about `ckeditor5-*` directories in development mode.
-	 *
-	 * @param {String} workspacePath Absolute path to workspace.
-	 * @param {Object} packageJSON Contents of `ckeditor5` repo `package.json` file.
-	 * @param {String} ckeditor5Path Absolute path to ckeditor5 root directory.
-	 * @param {Boolean} includeRoot Include main `ckeditor5` package.
-	 * @returns {Array.<Object>}
-	 */
-	getDevDirectories( workspacePath, packageJSON, ckeditor5Path, includeRoot ) {
-		const directories = this.getDirectories( workspacePath );
-		const dependencies = this.getDependencies( packageJSON.dependencies );
-
-		let devDirectories = [];
-
-		for ( let dependency in dependencies ) {
-			const repositoryURL = dependencies[ dependency ];
-			const urlInfo = git.parseRepositoryUrl( repositoryURL );
-			const repositoryPath = path.join( ckeditor5Path, 'node_modules', dependency );
-
-			// Check if repository's directory already exists.
-			if ( directories.indexOf( urlInfo.name ) > -1 ) {
-				devDirectories.push( {
-					repositoryPath,
-					repositoryURL
-				} );
-			}
-		}
-
-		if ( includeRoot ) {
-			// Add root dependency and directory.
-			devDirectories.unshift( {
-				repositoryPath: ckeditor5Path,
-				repositoryURL: 'ckeditor/ckeditor5'
-			} );
-		}
-
-		return devDirectories;
-	}
-};

+ 0 - 190
dev/utils/git.js

@@ -1,190 +0,0 @@
-/**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-const tools = require( './tools' );
-const defaultOrigin = 'origin';
-
-module.exports = {
-	/**
-	 * Parses GitHub URL. Extracts used server, repository and branch.
-	 *
-	 * @param {String} url GitHub URL from package.json file.
-	 * @returns {Object} urlInfo
-	 * @returns {String} urlInfo.server
-	 * @returns {String} urlInfo.repository
-	 * @returns {String} urlInfo.user
-	 * @returns {String} urlInfo.name
-	 * @returns {String} urlInfo.branch
-	 */
-	parseRepositoryUrl( url ) {
-		const regexp = /^((?:git@|(?:http[s]?|git):\/\/)github\.com(?:\/|:))?(([\w-]+)\/([\w-]+(?:\.git)?))(?:#([\w-\/]+))?$/;
-		const match = url.match( regexp );
-		let server;
-		let repository;
-		let branch;
-		let name;
-		let user;
-
-		if ( !match ) {
-			return null;
-		}
-
-		server = match[ 1 ] || 'git@github.com:';
-		repository = match[ 2 ];
-		user = match[ 3 ];
-		name = match[ 4 ];
-		branch = match[ 5 ] || 'master';
-
-		name = /\.git$/.test( name ) ? name.slice( 0, -4 ) : name;
-
-		return {
-			server: server,
-			repository: repository,
-			branch: branch,
-			user: user,
-			name: name
-		};
-	},
-
-	/**
-	 * Clones repository to workspace.
-	 *
-	 * @param {Object} urlInfo Parsed URL object from {@link #parseRepositoryUrl}.
-	 * @param {String} workspacePath Path to the workspace location where repository will be cloned.
-	 */
-	cloneRepository( urlInfo, workspacePath ) {
-		const cloneCommands = [
-			`cd ${ workspacePath }`,
-			`git clone ${ urlInfo.server + urlInfo.repository }`
-		];
-
-		tools.shExec( cloneCommands.join( ' && ' ) );
-	},
-
-	/**
-	 * Checks out branch on selected repository.
-	 *
-	 * @param {String} repositoryLocation Absolute path to repository.
-	 * @param {String} branchName Name of the branch to checkout.
-	 */
-	checkout( repositoryLocation, branchName ) {
-		const checkoutCommands = [
-			`cd ${ repositoryLocation }`,
-			`git checkout ${ branchName }`
-		];
-
-		tools.shExec( checkoutCommands.join( ' && ' ) );
-	},
-
-	/**
-	 * Pulls specified branch from origin.
-	 *
-	 * @param {String} repositoryLocation Absolute path to repository.
-	 * @param {String} branchName Branch name to pull.
-	 */
-	pull( repositoryLocation, branchName ) {
-		const pullCommands = [
-			`cd ${ repositoryLocation }`,
-			`git pull ${ defaultOrigin } ${ branchName }`
-		];
-
-		tools.shExec( pullCommands.join( ' && ' ) );
-	},
-
-	/**
-	 * Fetch all branches from each origin on selected repository.
-	 *
-	 * @param {String} repositoryLocation
-	 */
-	fetchAll( repositoryLocation ) {
-		const fetchCommands = [
-			`cd ${ repositoryLocation }`,
-			`git fetch --all`
-		];
-
-		tools.shExec( fetchCommands.join( ' && ' ) );
-	},
-
-	/**
-	 * Initializes new repository, adds and merges CKEditor5 boilerplate project.
-	 *
-	 * @param {String} repositoryPath Absolute path where repository should be created.
-	 */
-	initializeRepository( repositoryPath ) {
-		tools.shExec( `git init ${ repositoryPath }` );
-	},
-
-	/**
-	 * Returns Git status of repository stored under specified path. It runs `git status --porcelain -sb` command.
-	 *
-	 * @param {String} repositoryPath Absolute path to repository.
-	 * @returns {String} Executed command's result.
-	 */
-	getStatus( repositoryPath ) {
-		return tools.shExec( `cd ${ repositoryPath } && git status --porcelain -sb`, false );
-	},
-
-	/**
-	 * Creates initial commit on repository under specified path.
-	 *
-	 * @param {String} pluginName
-	 * @param {String} repositoryPath
-	 */
-	initialCommit( pluginName, repositoryPath ) {
-		const commitCommands = [
-			`cd ${ repositoryPath }`,
-			`git add .`,
-			`git commit -m "Initial commit for ${ pluginName }."`
-		];
-
-		tools.shExec( commitCommands.join( ' && ' ) );
-	},
-
-	/**
-	 * Adds remote to repository under specified path.
-	 *
-	 * @param {String} repositoryPath
-	 * @param {String} gitHubPath
-	 */
-	addRemote( repositoryPath, gitHubPath ) {
-		const addRemoteCommands = [
-			`cd ${ repositoryPath }`,
-			`git remote add ${ defaultOrigin } git@github.com:${ gitHubPath }.git`
-		];
-
-		tools.shExec( addRemoteCommands.join( ' && ' ) );
-	},
-
-	/*
-	 * Creates commit on repository under specified path
-	 *
-	 * @param {String} message
-	 * @param {String} repositoryPath
-	 */
-	commit( message, repositoryPath ) {
-		const commitCommands = [
-			`cd ${ repositoryPath }`,
-			`git commit --all --message "${ message }"`
-		];
-
-		tools.shExec( commitCommands.join( ' && ' ) );
-	},
-
-	/**
-	 * Pushes changes to repository's default location
-	 *
-	 * @param {String} repositoryPath
-	 */
-	push( repositoryPath ) {
-		const pushCommands = [
-			`cd ${ repositoryPath }`,
-			`git push`
-		];
-
-		tools.shExec( pushCommands.join( ' && ' ) );
-	}
-};

+ 0 - 58
dev/utils/log.js

@@ -1,58 +0,0 @@
-/**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-const gutil = require( 'gulp-util' );
-
-let logOut = ( msg ) => gutil.log( msg );
-let logErr = ( msg ) => gutil.log( gutil.colors.red( msg ) );
-
-module.exports = {
-	/**
-	 * Configure login output functions.
-	 *
-	 * 		log.configure( logOut, logErr );
-	 *
-	 * 		function logOut( message ) {
-	 * 			// Save output to file.
-	 * 			...
-	 * 		}
-	 *
-	 * 		function logErr( message) {
-	 * 			// Save error to file.
-	 * 			...
-	 * 		}
-	 *
-	 * @param {Function} stdout Function to be used to log standard output.
-	 * @param {Function} stderr Function to be used to log standard error.
-	 */
-	configure( stdout, stderr ) {
-		logOut = stdout;
-		logErr = stderr;
-	},
-
-	/**
-	 * Logs output using function provided in {@link configure}.
-	 *
-	 * @param {String} message Message to be logged.
-	 */
-	out( message ) {
-		if ( logOut ) {
-			logOut( message );
-		}
-	},
-
-	/**
-	 * Logs errors using function provided in {@link #configure}.
-	 *
-	 * @param {String} message Message to be logged.
-	 */
-	err( message ) {
-		if ( logErr ) {
-			logErr( message );
-		}
-	}
-};

+ 0 - 290
dev/utils/tools.js

@@ -1,290 +0,0 @@
-/**
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-'use strict';
-
-const gutil = require( 'gulp-util' );
-const path = require( 'path' );
-const del = require( 'del' );
-
-module.exports = {
-	/**
-	 * Executes a shell command.
-	 *
-	 * @param {String} command The command to be executed.
-	 * @param {Boolean} [logOutput] When set to `false` command's output will not be logged. When set to `true`,
-	 * stdout and stderr will be logged. Defaults to `true`.
-	 * @returns {String} The command output.
-	 */
-	shExec( command, logOutput ) {
-		const sh = require( 'shelljs' );
-
-		sh.config.silent = true;
-		logOutput = logOutput !== false;
-
-		const ret = sh.exec( command );
-		const logColor = ret.code ? gutil.colors.red : gutil.colors.grey;
-
-		if ( logOutput ) {
-			if ( ret.stdout ) {
-				console.log( '\n' + logColor( ret.stdout.trim() ) + '\n' );
-			}
-
-			if ( ret.stderr ) {
-				console.log( '\n' + gutil.colors.grey( ret.stderr.trim() ) + '\n' );
-			}
-		}
-
-		if ( ret.code ) {
-			throw new Error( `Error while executing ${ command }: ${ ret.stderr }` );
-		}
-
-		return ret.stdout;
-	},
-
-	/**
-	 * Links directory located in source path to directory located in destination path.
-	 * @param {String} source
-	 * @param {String} destination
-	 */
-	linkDirectories( source, destination ) {
-		const fs = require( 'fs' );
-		// Remove destination directory if exists.
-		if ( this.isSymlink( destination ) ) {
-			this.removeSymlink( destination );
-		} else if ( this.isDirectory( destination ) ) {
-			this.shExec( `rm -rf ${ destination }` );
-		}
-
-		fs.symlinkSync( source, destination, 'dir' );
-	},
-
-	/**
-	 * Returns array with all directories under specified path.
-	 *
-	 * @param {String} path
-	 * @returns {Array}
-	 */
-	getDirectories( path ) {
-		const fs = require( 'fs' );
-		const pth = require( 'path' );
-
-		return fs.readdirSync( path ).filter( item => {
-			return this.isDirectory( pth.join( path, item ) );
-		} );
-	},
-
-	/**
-	 * Returns true if path points to existing directory.
-	 *
-	 * @param {String} path
-	 * @returns {Boolean}
-	 */
-	isDirectory( path ) {
-		const fs = require( 'fs' );
-
-		try {
-			return fs.statSync( path ).isDirectory();
-		} catch ( e ) {}
-
-		return false;
-	},
-
-	/**
-	 * Returns true if path points to existing file.
-	 *
-	 * @param {String} path
-	 * @returns {Boolean}
-	 */
-	isFile( path ) {
-		const fs = require( 'fs' );
-
-		try {
-			return fs.statSync( path ).isFile();
-		} catch ( e ) {}
-
-		return false;
-	},
-
-	/**
-	 * Returns true if path points to symbolic link.
-	 *
-	 * @param {String} path
-	 */
-	isSymlink( path ) {
-		const fs = require( 'fs' );
-
-		try {
-			return fs.lstatSync( path ).isSymbolicLink();
-		} catch ( e ) {}
-
-		return false;
-	},
-
-	/**
-	 * Updates JSON file under specified path.
-	 * @param {String} path Path to file on disk.
-	 * @param {Function} updateFunction Function that will be called with parsed JSON object. It should return
-	 * modified JSON object to save.
-	 */
-	updateJSONFile( path, updateFunction ) {
-		const fs = require( 'fs' );
-
-		const contents = fs.readFileSync( path, 'utf-8' );
-		let json = JSON.parse( contents );
-		json = updateFunction( json );
-
-		fs.writeFileSync( path, JSON.stringify( json, null, 2 ) + '\n', 'utf-8' );
-	},
-
-	/**
-	 * Reinserts all object's properties in alphabetical order (character's Unicode value).
-	 * Used for JSON.stringify method which takes keys in insertion order.
-	 *
-	 * @param { Object } obj
-	 * @returns { Object } Same object with sorted keys.
-	 */
-	sortObject( obj ) {
-		Object.keys( obj ).sort().forEach( key => {
-			const val = obj[ key ];
-			delete obj[ key ];
-			obj[ key ] = val;
-		} );
-
-		return obj;
-	},
-
-	/**
-	 * Returns name of the NPM module located under provided path.
-	 *
-	 * @param {String} modulePath Path to NPM module.
-     */
-	readPackageName( modulePath ) {
-		const fs = require( 'fs' );
-		const path = require( 'path' );
-		const packageJSONPath = path.join( modulePath, 'package.json' );
-
-		if ( !this.isFile( packageJSONPath ) ) {
-			return null;
-		}
-
-		const contents = fs.readFileSync( packageJSONPath, 'utf-8' );
-		const json = JSON.parse( contents );
-
-		return json.name || null;
-	},
-
-	/**
-	 * Calls `npm install` command in specified path.
-	 *
-	 * @param {String} path
-	 */
-	npmInstall( path ) {
-		this.shExec( `cd ${ path } && npm install` );
-	},
-
-	/**
-	 * Calls `npm uninstall <name>` command in specified path.
-	 *
-	 * @param {String} path
-	 * @param {String} name
-	 */
-	npmUninstall( path, name ) {
-		this.shExec( `cd ${ path } && npm uninstall ${ name }` );
-	},
-
-	/**
-	 * Calls `npm update --dev` command in specified path.
-	 *
-	 * @param {String} path
-	 */
-	npmUpdate( path ) {
-		this.shExec( `cd ${ path } && npm update --dev` );
-	},
-
-	/**
-	 * Copies source files into destination directory and replaces contents of the file using provided `replace` object.
-	 *
-	 *		// Each occurrence of `{{appName}}` inside README.md and CHANGES.md will be changed to `ckeditor5`.
-	 * 		tools.copyTemplateFiles( [ 'README.md', 'CHANGES.md' ], '/new/path', { '{{AppName}}': 'ckeditor5' } );
-	 *
-	 * @param {Array} sources Source files.
-	 * @param {String} destination Path to destination directory.
-	 * @param {Object} [replace] Object with data to fill template. Method will take object's keys and replace their
-	 * occurrences with value stored under that key.
-	 */
-	copyTemplateFiles( sources, destination, replace ) {
-		const path = require( 'path' );
-		const fs = require( 'fs-extra' );
-		replace = replace || {};
-		destination = path.resolve( destination );
-		const regexps = [];
-
-		for ( let variableName in replace ) {
-			regexps.push( variableName );
-		}
-		const regexp = new RegExp( regexps.join( '|' ), 'g' );
-		const replaceFunction = ( matched ) => replace[ matched ];
-
-		fs.ensureDirSync( destination );
-
-		sources.forEach( source => {
-			source = path.resolve( source );
-			let fileData = fs.readFileSync( source, 'utf8' );
-			fileData = fileData.replace( regexp, replaceFunction );
-			fs.writeFileSync( path.join( destination, path.basename( source ) ), fileData, 'utf8' );
-		} );
-	},
-
-	/**
-	 * Executes 'npm view' command for provided module name and returns Git url if one is found. Returns null if
-	 * module cannot be found.
-	 *
-	 * @param {String} name Name of the module.
-	 * @returns {*}
-     */
-	getGitUrlFromNpm( name ) {
-		try {
-			const info = JSON.parse( this.shExec( `npm view ${ name } repository --json`, false ) );
-
-			if ( info && info.type == 'git' ) {
-				return info.url;
-			}
-		} catch ( error ) {
-			// Throw error only when different than E404.
-			if ( error.message.indexOf( 'npm ERR! code E404' ) == -1 ) {
-				throw error;
-			}
-		}
-
-		return null;
-	},
-
-	/**
-	 * Unlinks symbolic link under specified path.
-	 *
-	 * @param {String} path
-	 */
-	removeSymlink( path ) {
-		const fs = require( 'fs' );
-		fs.unlinkSync( path );
-	},
-
-	/**
-	 * Removes files and directories specified by `glob` starting from `rootDir`
-	 * and gently informs about deletion.
-	 *
-	 * @param {String} rootDir The path to the root directory (i.e. "dist/").
-	 * @param {String} glob Glob specifying what to clean.
-	 * @returns {Promise}
-	 */
-	clean( rootDir, glob ) {
-		return del( path.join( rootDir, glob ) ).then( paths => {
-			paths.forEach( p => {
-				gutil.log( `Deleted file '${ gutil.colors.cyan( p ) }'.` );
-			} );
-		} );
-	}
-};

+ 3 - 9
package.json

@@ -23,7 +23,6 @@
     "requirejs": "Reinmar/requirejs"
   },
   "devDependencies": {
-    "almond": "^0.3.0",
     "babel-core": "^6.9.0",
     "babel-plugin-transform-es2015-modules-amd": "^6.8.0",
     "babel-plugin-transform-es2015-modules-commonjs": "^6.10.0",
@@ -35,9 +34,8 @@
     "benderjs-promise": "^0.1.0",
     "benderjs-sinon": "^0.3.0",
     "chai": "^3.4.0",
+    "ckeditor5-dev-utils": "ckeditor/ckeditor5-dev-utils",
     "concat-stream": "^1.5.1",
-    "del": "^2.0.2",
-    "fs-extra": "^0.26.4",
     "git-guppy": "^1.1.0",
     "gulp": "^3.9.0",
     "gulp-babel": "^6.1.0",
@@ -68,20 +66,16 @@
     "minimist": "^1.2.0",
     "mkdirp": "^0.5.1",
     "mockery": "^1.4.0",
-    "multipipe": "^0.3.0",
-    "ncp": "^2.0.0",
-    "node-sass": "^3.7.0",
     "parse-gitignore": "^0.2.0",
     "pretty-bytes": "^3.0.1",
     "regenerator-runtime": "^0.9.5",
-    "replace": "^0.3.0",
     "rollup": "^0.33.0",
     "rollup-plugin-babel": "^2.4.0",
     "run-sequence": "^1.1.5",
     "semver": "^5.1.0",
-    "shelljs": "^0",
     "sinon": "^1.17.0",
-    "through2": "^2.0.0"
+    "through2": "^2.0.0",
+    "vinyl": "^1.1.1"
   },
   "engines": {
     "node": ">=6.0.0",