utils.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /* jshint node: true, esnext: true */
  2. 'use strict';
  3. const path = require( 'path' );
  4. const gulp = require( 'gulp' );
  5. const rename = require( 'gulp-rename' );
  6. const babel = require( 'gulp-babel' );
  7. const gulpWatch = require( 'gulp-watch' );
  8. const gulpPlumber = require( 'gulp-plumber' );
  9. const gutil = require( 'gulp-util' );
  10. const multipipe = require( 'multipipe' );
  11. const stream = require( 'stream' );
  12. const sep = path.sep;
  13. const utils = {
  14. /**
  15. * Returns a stream of files matching the given glob pattern.
  16. *
  17. * @param {String} root The root directory.
  18. * @param {String} glob The glob pattern.
  19. * @param {Boolean} [watch] Whether to watch the files.
  20. * @returns {Stream}
  21. */
  22. src( root, glob, watch ) {
  23. const srcDir = path.join( root, glob );
  24. let stream = gulp.src( srcDir );
  25. if ( watch ) {
  26. stream = stream
  27. // Let's use plumber only when watching. In other cases we should fail quickly and loudly.
  28. .pipe( gulpPlumber() )
  29. .pipe( gulpWatch( srcDir ) );
  30. }
  31. return stream;
  32. },
  33. /**
  34. * Saves the files piped into this stream to the `dist/` directory.
  35. *
  36. * @param {String} distDir The `dist/` directory path.
  37. * @param {String} format The format of the distribution (`esnext`, `amd`, or `cjs`).
  38. * @returns {Stream}
  39. */
  40. dist( distDir, format ) {
  41. const destDir = path.join( distDir, format );
  42. return gulp.dest( destDir );
  43. },
  44. /**
  45. * Transpiles files piped into this stream to the given format (`amd` or `cjs`).
  46. *
  47. * @param {String} format
  48. * @returns {Stream}
  49. */
  50. transpile( format ) {
  51. const babelModuleTranspilers = {
  52. amd: 'amd',
  53. cjs: 'commonjs'
  54. };
  55. const babelModuleTranspiler = babelModuleTranspilers[ format ];
  56. if ( !babelModuleTranspiler ) {
  57. throw new Error( `Incorrect format: ${ format }` );
  58. }
  59. return new stream.PassThrough( { objectMode: true } )
  60. // Not used so far, but we'll need it.
  61. // .pipe( utils.pickVersionedFile( format ) )
  62. .pipe( babel( {
  63. plugins: [ `transform-es2015-modules-${ babelModuleTranspiler }` ]
  64. } ) );
  65. },
  66. /**
  67. * Creates a function adding transpilation pipes to the `pipes` param.
  68. * Used to generate `formats.reduce()` callback where `formats` is an array
  69. * of formats that should be generated.
  70. *
  71. * @param {String} distDir The `dist/` directory path.
  72. * @returns {Function}
  73. */
  74. addFormat( distDir ) {
  75. return ( pipes, format ) => {
  76. const conversionPipes = [];
  77. if ( format != 'esnext' ) {
  78. conversionPipes.push( utils.transpile( format ) );
  79. }
  80. conversionPipes.push(
  81. utils.dist( distDir, format )
  82. .on( 'data', ( file ) => {
  83. gutil.log( `Finished writing '${ gutil.colors.cyan( file.path ) }'` );
  84. } )
  85. );
  86. pipes.push( multipipe.apply( null, conversionPipes ) );
  87. return pipes;
  88. };
  89. },
  90. // Not used so far, but will allow us to pick one of files suffixed with the format (`__esnext`, `__amd`, or `__cjs`).
  91. // This will be needed when we'll want to have different piece of code for specific formats.
  92. //
  93. // For example: we'll have `loader__esnext.js`, `loader__amd.js` and `loader__cjs.js`. After applying this
  94. // transformation when compiling code for a specific format the proper file will be renamed to `loader.js`.
  95. pickVersionedFile( format ) {
  96. return rename( ( path ) => {
  97. const regexp = new RegExp( `__${ format }$` );
  98. path.basename = path.basename.replace( regexp, '' );
  99. } );
  100. },
  101. /**
  102. * Moves files out of `node_modules/ckeditor5-xxx/src/*` directories to `ckeditor5-xxx/*`.
  103. *
  104. * @param {RegExp} modulePathPattern
  105. * @returns {Stream}
  106. */
  107. unpackModules( modulePathPattern ) {
  108. return rename( ( filePath ) => {
  109. filePath.dirname = filePath.dirname.replace( modulePathPattern, `${ sep }$1${ sep }` );
  110. // Remove now empty src/ dirs.
  111. if ( !filePath.extname && filePath.basename == 'src' ) {
  112. filePath.basename = '';
  113. }
  114. } );
  115. },
  116. /**
  117. * Adds `ckeditor5/` to a file path.
  118. *
  119. * @returns {Stream}
  120. */
  121. wrapCKEditor5Module() {
  122. return rename( ( filePath ) => {
  123. filePath.dirname = path.join( filePath.dirname, 'ckeditor5' );
  124. } );
  125. }
  126. };
  127. module.exports = utils;