index.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. 'use strict';
  2. var fs = require('fs');
  3. var os = require('os');
  4. var path = require('path');
  5. var rimraf = require('rimraf');
  6. // added node .10
  7. // http://stackoverflow.com/questions/21698906/how-to-check-if-a-path-is-absolute-or-relative/30714706#30714706
  8. function isAbsolute(dir) {
  9. return path.normalize(dir + path.sep) === path.normalize(path.resolve(dir) + path.sep);
  10. }
  11. function upperCaseWindowsRoot(dir) {
  12. var splitPath = dir.split(path.sep);
  13. splitPath[0] = splitPath[0].toUpperCase();
  14. return splitPath.join(path.sep);
  15. }
  16. function CleanWebpackPlugin(paths, options) {
  17. //backwards compatibility
  18. if (typeof options === 'string') {
  19. options = {
  20. root: options
  21. }
  22. }
  23. options = options || {};
  24. if (options.verbose === undefined) {
  25. if (process.env.NODE_ENV === 'test') {
  26. options.verbose = false;
  27. } else {
  28. options.verbose = true;
  29. }
  30. }
  31. options.allowExternal = options.allowExternal || false;
  32. if (options.dry === undefined) {
  33. options.dry = false;
  34. }
  35. // determine webpack root
  36. options.root = options.root || path.dirname(module.parent.filename);
  37. // allows for a single string entry
  38. if (typeof paths == 'string' || paths instanceof String) {
  39. paths = [paths];
  40. }
  41. // store paths and options
  42. this.paths = paths;
  43. this.options = options;
  44. }
  45. var clean = function() {
  46. var _this = this;
  47. var results = [];
  48. var workingDir;
  49. var dirName;
  50. var projectRootDir;
  51. var webpackDir;
  52. // exit if no paths passed in
  53. if (_this.paths === void 0) {
  54. results.push({ path: _this.paths, output: 'nothing to clean' });
  55. return results;
  56. }
  57. if (!isAbsolute(_this.options.root)) {
  58. _this.options.verbose && console.warn(
  59. 'clean-webpack-plugin: ' + _this.options.root +
  60. ' project root must be an absolute path. Skipping all...');
  61. results.push({ path: _this.options.root, output: 'project root must be an absolute path' });
  62. return results;
  63. }
  64. workingDir = process.cwd();
  65. dirName = __dirname;
  66. projectRootDir = path.resolve(_this.options.root);
  67. webpackDir = path.dirname(module.parent.filename);
  68. if (os.platform() === 'win32') {
  69. workingDir = upperCaseWindowsRoot(workingDir);
  70. dirName = upperCaseWindowsRoot(dirName);
  71. projectRootDir = upperCaseWindowsRoot(projectRootDir);
  72. webpackDir = upperCaseWindowsRoot(webpackDir);
  73. }
  74. // preform an rm -rf on each path
  75. _this.paths.forEach(function(rimrafPath) {
  76. rimrafPath = path.resolve(_this.options.root, rimrafPath);
  77. if (os.platform() === 'win32') {
  78. rimrafPath = upperCaseWindowsRoot(rimrafPath);
  79. }
  80. // disallow deletion any directories outside of root path.
  81. if (rimrafPath.indexOf(projectRootDir) < 0 && !_this.options.allowExternal) {
  82. _this.options.verbose && console.warn(
  83. 'clean-webpack-plugin: ' + rimrafPath + ' is outside of the project root. Skipping...');
  84. results.push({ path: rimrafPath, output: 'must be inside the project root' });
  85. return;
  86. }
  87. if (rimrafPath === projectRootDir) {
  88. _this.options.verbose &&
  89. console.warn(
  90. 'clean-webpack-plugin: ' + rimrafPath + ' is equal to project root. Skipping...');
  91. results.push({ path: rimrafPath, output: 'is equal to project root' });
  92. return;
  93. }
  94. if (rimrafPath === webpackDir) {
  95. _this.options.verbose &&
  96. console.warn('clean-webpack-plugin: ' + rimrafPath + ' would delete webpack. Skipping...');
  97. results.push({ path: rimrafPath, output: 'would delete webpack' });
  98. return;
  99. }
  100. if (rimrafPath === dirName || rimrafPath === workingDir) {
  101. _this.options.verbose &&
  102. console.log('clean-webpack-plugin: ' + rimrafPath + ' is working directory. Skipping...');
  103. results.push({ path: rimrafPath, output: 'is working directory' });
  104. return;
  105. }
  106. var childrenAfterExcluding = [];
  107. var excludedChildren = [];
  108. if (_this.options.exclude && _this.options.exclude.length) {
  109. try {
  110. var pathStat = fs.statSync(rimrafPath);
  111. if (pathStat.isDirectory()) {
  112. childrenAfterExcluding = fs.readdirSync(rimrafPath)
  113. .filter(function(childFile) {
  114. var include = _this.options.exclude.indexOf(childFile) < 0;
  115. if (!include) {
  116. excludedChildren.push(childFile);
  117. }
  118. return include;
  119. })
  120. .map(function(file) {
  121. var fullPath = path.join(rimrafPath, file);
  122. if (os.platform() === 'win32') {
  123. fullPath = upperCaseWindowsRoot(fullPath);
  124. }
  125. return fullPath;
  126. });
  127. }
  128. if (_this.options.exclude.indexOf('.') >= 0) {
  129. excludedChildren.push('.');
  130. }
  131. } catch (e) {
  132. childrenAfterExcluding = [];
  133. }
  134. }
  135. if (_this.options.dry !== true) {
  136. if (_this.options.exclude && excludedChildren.length) {
  137. childrenAfterExcluding.forEach(function(child) {
  138. rimraf.sync(child);
  139. });
  140. } else {
  141. rimraf.sync(rimrafPath);
  142. }
  143. }
  144. _this.options.verbose &&
  145. console.warn('clean-webpack-plugin: ' + rimrafPath + ' has been removed.');
  146. _this.options.verbose && excludedChildren.length &&
  147. console.warn('clean-webpack-plugin: ' + excludedChildren.length + ' file(s) excluded - ' + excludedChildren.join(', '));
  148. excludedChildren.length ?
  149. results.push({ path: rimrafPath, output: 'removed with exclusions (' + excludedChildren.length + ')' }) :
  150. results.push({ path: rimrafPath, output: 'removed' });
  151. });
  152. return results;
  153. };
  154. CleanWebpackPlugin.prototype.apply = function(compiler) {
  155. var _this = this;
  156. if (compiler === undefined) {
  157. return clean.call(_this);
  158. } else {
  159. if (_this.options.watch) {
  160. compiler.plugin("compile", function(params) {
  161. clean.call(_this);
  162. });
  163. } else {
  164. return clean.call(_this);
  165. }
  166. }
  167. };
  168. module.exports = CleanWebpackPlugin;