123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- 'use strict';
- const path = require('path');
- function CaseSensitivePathsPlugin(options) {
- this.options = options || {};
- this.logger = this.options.logger || console;
- this.reset();
- }
- CaseSensitivePathsPlugin.prototype.reset = function () {
- this.pathCache = {};
- this.fsOperations = 0;
- this.primed = false;
- };
- CaseSensitivePathsPlugin.prototype.getFilenamesInDir = function (dir, callback) {
- const that = this;
- const fs = this.compiler.inputFileSystem;
- this.fsOperations += 1;
- if (Object.prototype.hasOwnProperty.call(this.pathCache, dir)) {
- callback(this.pathCache[dir]);
- return;
- }
- if (this.options.debug) {
- this.logger.log('[CaseSensitivePathsPlugin] Reading directory', dir);
- }
- fs.readdir(dir, (err, files) => {
- if (err) {
- if (that.options.debug) {
- this.logger.log('[CaseSensitivePathsPlugin] Failed to read directory', dir, err);
- }
- callback([]);
- return;
- }
- callback(files.map((f) => f.normalize ? f.normalize('NFC') : f));
- });
- };
- CaseSensitivePathsPlugin.prototype.fileExistsWithCase = function (filepath, callback) {
-
- const that = this;
- const dir = path.dirname(filepath);
- const filename = path.basename(filepath);
- const parsedPath = path.parse(dir);
-
- if (parsedPath.dir === parsedPath.root || dir === '.' || Object.prototype.hasOwnProperty.call(that.pathCache, filepath)) {
- callback();
- return;
- }
-
-
- that.getFilenamesInDir(dir, (filenames) => {
-
- if (filenames.indexOf(filename) === -1) {
-
- let correctFilename = '!nonexistent';
- for (let i = 0; i < filenames.length; i += 1) {
- if (filenames[i].toLowerCase() === filename.toLowerCase()) {
- correctFilename = `\`${filenames[i]}\`.`;
- break;
- }
- }
- callback(correctFilename);
- return;
- }
-
- that.fileExistsWithCase(dir, (recurse) => {
-
-
- if (!recurse) {
- that.pathCache[dir] = filenames;
- }
- callback(recurse);
- });
- });
- };
- CaseSensitivePathsPlugin.prototype.primeCache = function (callback) {
- if (this.primed) {
- callback();
- return;
- }
- const that = this;
-
-
- const currentPath = path.resolve();
- that.getFilenamesInDir(currentPath, (files) => {
- that.pathCache[currentPath] = files;
- that.primed = true;
- callback();
- });
- };
- CaseSensitivePathsPlugin.prototype.apply = function (compiler) {
- this.compiler = compiler;
- const onDone = () => {
- if (this.options.debug) {
- this.logger.log('[CaseSensitivePathsPlugin] Total filesystem reads:', this.fsOperations);
- }
- this.reset();
- };
- const checkFile = (pathName, data, done) => {
- this.fileExistsWithCase(pathName, (realName) => {
- if (realName) {
- if (realName === '!nonexistent') {
-
- if (data.createData) done(null); else done(null, data);
- } else {
- done(new Error(`[CaseSensitivePathsPlugin] \`${pathName}\` does not match the corresponding path on disk ${realName}`));
- }
- } else if (data.createData) {
- done(null);
- } else {
- done(null, data);
- }
- });
- };
- const onAfterResolve = (data, done) => {
- this.primeCache(() => {
-
- let pathName = (data.createData || data).resource.split('?')[0];
- pathName = pathName.normalize ? pathName.normalize('NFC') : pathName;
- checkFile(pathName, data, done);
- });
- };
- if (compiler.hooks) {
- compiler.hooks.done.tap('CaseSensitivePathsPlugin', onDone);
- if (this.options.useBeforeEmitHook) {
- if (this.options.debug) {
- this.logger.log('[CaseSensitivePathsPlugin] Using the hook for before emit.');
- }
- compiler.hooks.emit.tapAsync('CaseSensitivePathsPlugin', (compilation, callback) => {
- let resolvedFilesCount = 0;
- const errors = [];
- this.primeCache(() => {
- compilation.fileDependencies.forEach((filename) => {
- checkFile(filename, filename, (error) => {
- resolvedFilesCount += 1;
- if (error) {
- errors.push(error);
- }
- if (resolvedFilesCount === compilation.fileDependencies.size) {
- if (errors.length) {
-
- Array.prototype.push.apply(compilation.errors, errors);
- }
- callback();
- }
- });
- });
- });
- });
- } else {
- compiler.hooks.normalModuleFactory.tap('CaseSensitivePathsPlugin', (nmf) => {
- nmf.hooks.afterResolve.tapAsync('CaseSensitivePathsPlugin', onAfterResolve);
- });
- }
- } else {
- compiler.plugin('done', onDone);
- compiler.plugin('normal-module-factory', (nmf) => {
- nmf.plugin('after-resolve', onAfterResolve);
- });
- }
- };
- module.exports = CaseSensitivePathsPlugin;
|