Files

235 lines
6.9 KiB
JavaScript

'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _mkdirp = require('mkdirp');
var _mkdirp2 = _interopRequireDefault(_mkdirp);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var DEFAULT_FILE_SYSTEM_SYMBOL = Symbol('DefaultFileSystem');
class AssetModulePlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
var _this = this;
compiler.plugin('compilation', function (compilation, parameters) {
var addedResources = new Set();
compilation._modulesToEmit = [];
compilation.plugin('succeed-module', function (module) {
var resource = module.resource;
if (addedResources.has(resource) || !_this._shouldEmit(module)) {
return;
}
addedResources.add(resource);
compilation._modulesToEmit.push(module);
});
});
compiler.plugin('after-emit', function (compilation, callback) {
Promise.all(compilation._modulesToEmit.map(function (module) {
return _this._emitAssetModule(compiler, compilation, module);
})).then(function (result) {
callback(null, result);
}, function (error) {
console.warn(error.stack);
callback(error);
});
});
}
_emitAssetModule(compiler, compilation, module) {
var _this2 = this;
var _options = this.options;
var sourceBase = _options.sourceBase;
var destinationBase = _options.destinationBase;
var resource = module.resource;
var relativePath = _path2.default.relative(sourceBase, resource);
var destinationPath = _path2.default.resolve(destinationBase, relativePath);
if (resource === destinationPath) {
var message = `Destination path for ${ resource } matches the source path; skipping instead of overwriting the file`;
compilation.warnings.push(new Error(message));
return Promise.resolve(null);
}
var source = this._getAssetModuleSource(compilation, module);
if (!this.options.fileSystems) {
var fileSystem = compiler.outputFileSystem;
return this._writeFile(destinationPath, source, fileSystem);
}
var fileSystems = this.options.fileSystems.map(function (fileSystem) {
if (fileSystem === DEFAULT_FILE_SYSTEM_SYMBOL) {
return compiler.outputFileSystem;
}
return fileSystem;
});
var promises = fileSystems.map(function (fileSystem) {
return _this2._writeFile(destinationPath, source, fileSystem).catch(function (error) {
compilation.errors.push(error);
throw error;
});
});
return Promise.all(promises);
}
_getAssetModuleSource(compilation, module) {
var sourceBase = this.options.sourceBase;
var resource = module.resource;
var assets = module.assets;
var publicPath = compilation.mainTemplate.getPublicPath({
hash: compilation.hash
});
var assetFilename;
var assetFilenames = Object.keys(assets);
if (assetFilenames.length === 0) {
assetFilename = _path2.default.relative(sourceBase, resource);
} else {
if (assetFilenames.length > 1) {
var message = `Module at ${ resource } generated more than one asset; using the first one`;
compilation.warnings.push(new Error(message));
}
assetFilename = assetFilenames[0];
}
var fullAssetPath = publicPath + assetFilename;
return `module.exports = ${ JSON.stringify(fullAssetPath) };\n`;
}
_writeFile(filename, content, fileSystem) {
var makeDirectories = this._getMakeDirectoriesFunction(fileSystem);
return new Promise(function (resolve, reject) {
makeDirectories(_path2.default.dirname(filename), function (error) {
if (error) {
reject(error);
return;
}
fileSystem.writeFile(filename, content, function (error) {
if (error) {
reject(error);
} else {
resolve(null);
}
});
});
});
}
_getMakeDirectoriesFunction(fileSystem) {
if (fileSystem.mkdirp) {
return fileSystem.mkdirp.bind(fileSystem);
}
return function (path, callback) {
return (0, _mkdirp2.default)(path, { fs: fileSystem }, callback);
};
}
_shouldEmit(module) {
var _options2 = this.options;
var test = _options2.test;
var include = _options2.include;
var exclude = _options2.exclude;
var resource = module.resource;
if (test && !this._matches(test, resource)) {
return false;
}
if (include && !this._matches(include, resource)) {
return false;
}
if (exclude && this._matches(exclude, resource)) {
return false;
}
return true;
}
_matches(pattern, string) {
if (pattern instanceof RegExp) {
return pattern.test(string);
}
if (typeof pattern === 'string') {
var escapedPattern = '^' + pattern.replace(/[-[\]{}()*+?.\\^$|]/g, '\\$&');
var regex = new RegExp(escapedPattern);
return regex.test(string);
}
if (typeof pattern === 'function') {
return pattern(string);
}
throw new Error(`Unsupported pattern: ${ pattern }`);
}
}
AssetModulePlugin.DefaultFileSystem = DEFAULT_FILE_SYSTEM_SYMBOL;
exports.default = AssetModulePlugin;
module.exports = exports.default;
/**
* The base directory of the source assets. This is the portion of the asset
* path that will be replaced with the destination base directory.
*
* For example, if `sourceBase` is `'src/web'` and `destinationBase` is
* `'build/web'`, then an asset at `src/web/assets/icon.png` would produce a
* module at `build/web/assets/icon.png`.
*
* The source assets don't need to reside in the source base directory. This
* plugin computes the relative path from the source base directory to each
* asset and applies the same relative path to the destination base directory.
* For example, with the previous example's configuration, an asset at
* `src/favicons/favicon.png` would result in a module at
* `build/favicons/favicon.png`.
*/
/**
* The base directory of the emitted modules. See the documentation for
* `sourceBase`.
*/
/**
* A test applied to each asset's resource path to determine if this plugin
* should emit a module for the asset. The test can be any of the types that
* webpack's loader patterns support.
*/
/**
* A test applied to each asset's resource path to determine if this plugin
* should emit a module for the asset.
*/
/**
* A test applied to each asset's resource path to determine if this plugin
* should not emit a module for the asset.
*/
/**
* Overrides the file systems used to write the emitted modules. By default,
* the plugin writes to the compiler's `outputFileSystem`, but you may want
* to write the modules to another file system as well.
*
* Specify `AssetModulePlugin.DefaultFileSystem` in the array to write to the
* compiler's `outputFileSystem`.
*/