mirror of https://github.com/webpack/webpack.git
				
				
				
			
		
			
				
	
	
		
			133 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
/*
 | 
						|
	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
						|
	Author Tobias Koppers @sokra
 | 
						|
*/
 | 
						|
 | 
						|
"use strict";
 | 
						|
 | 
						|
const { ConcatSource } = require("webpack-sources");
 | 
						|
const Compilation = require("./Compilation");
 | 
						|
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
 | 
						|
const Template = require("./Template");
 | 
						|
const createSchemaValidation = require("./util/create-schema-validation");
 | 
						|
 | 
						|
/** @typedef {import("../declarations/plugins/BannerPlugin").BannerFunction} BannerFunction */
 | 
						|
/** @typedef {import("../declarations/plugins/BannerPlugin").BannerPluginArgument} BannerPluginArgument */
 | 
						|
/** @typedef {import("../declarations/plugins/BannerPlugin").BannerPluginOptions} BannerPluginOptions */
 | 
						|
/** @typedef {import("./Compiler")} Compiler */
 | 
						|
 | 
						|
const validate = createSchemaValidation(
 | 
						|
	require("../schemas/plugins/BannerPlugin.check.js"),
 | 
						|
	() => require("../schemas/plugins/BannerPlugin.json"),
 | 
						|
	{
 | 
						|
		name: "Banner Plugin",
 | 
						|
		baseDataPath: "options"
 | 
						|
	}
 | 
						|
);
 | 
						|
 | 
						|
/**
 | 
						|
 * @param {string} str string to wrap
 | 
						|
 * @returns {string} wrapped string
 | 
						|
 */
 | 
						|
const wrapComment = str => {
 | 
						|
	if (!str.includes("\n")) {
 | 
						|
		return Template.toComment(str);
 | 
						|
	}
 | 
						|
	return `/*!\n * ${str
 | 
						|
		.replace(/\*\//g, "* /")
 | 
						|
		.split("\n")
 | 
						|
		.join("\n * ")
 | 
						|
		.replace(/\s+\n/g, "\n")
 | 
						|
		.trimEnd()}\n */`;
 | 
						|
};
 | 
						|
 | 
						|
class BannerPlugin {
 | 
						|
	/**
 | 
						|
	 * @param {BannerPluginArgument} options options object
 | 
						|
	 */
 | 
						|
	constructor(options) {
 | 
						|
		if (typeof options === "string" || typeof options === "function") {
 | 
						|
			options = {
 | 
						|
				banner: options
 | 
						|
			};
 | 
						|
		}
 | 
						|
 | 
						|
		validate(options);
 | 
						|
 | 
						|
		this.options = options;
 | 
						|
 | 
						|
		const bannerOption = options.banner;
 | 
						|
		if (typeof bannerOption === "function") {
 | 
						|
			const getBanner = bannerOption;
 | 
						|
			this.banner = this.options.raw
 | 
						|
				? getBanner
 | 
						|
				: /** @type {BannerFunction} */ data => wrapComment(getBanner(data));
 | 
						|
		} else {
 | 
						|
			const banner = this.options.raw
 | 
						|
				? bannerOption
 | 
						|
				: wrapComment(bannerOption);
 | 
						|
			this.banner = () => banner;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Apply the plugin
 | 
						|
	 * @param {Compiler} compiler the compiler instance
 | 
						|
	 * @returns {void}
 | 
						|
	 */
 | 
						|
	apply(compiler) {
 | 
						|
		const options = this.options;
 | 
						|
		const banner = this.banner;
 | 
						|
		const matchObject = ModuleFilenameHelpers.matchObject.bind(
 | 
						|
			undefined,
 | 
						|
			options
 | 
						|
		);
 | 
						|
		const cache = new WeakMap();
 | 
						|
		const stage =
 | 
						|
			this.options.stage || Compilation.PROCESS_ASSETS_STAGE_ADDITIONS;
 | 
						|
 | 
						|
		compiler.hooks.compilation.tap("BannerPlugin", compilation => {
 | 
						|
			compilation.hooks.processAssets.tap(
 | 
						|
				{
 | 
						|
					name: "BannerPlugin",
 | 
						|
					stage
 | 
						|
				},
 | 
						|
				() => {
 | 
						|
					for (const chunk of compilation.chunks) {
 | 
						|
						if (options.entryOnly && !chunk.canBeInitial()) {
 | 
						|
							continue;
 | 
						|
						}
 | 
						|
 | 
						|
						for (const file of chunk.files) {
 | 
						|
							if (!matchObject(file)) {
 | 
						|
								continue;
 | 
						|
							}
 | 
						|
 | 
						|
							const data = {
 | 
						|
								chunk,
 | 
						|
								filename: file
 | 
						|
							};
 | 
						|
 | 
						|
							const comment = compilation.getPath(banner, data);
 | 
						|
 | 
						|
							compilation.updateAsset(file, old => {
 | 
						|
								let cached = cache.get(old);
 | 
						|
								if (!cached || cached.comment !== comment) {
 | 
						|
									const source = options.footer
 | 
						|
										? new ConcatSource(old, "\n", comment)
 | 
						|
										: new ConcatSource(comment, "\n", old);
 | 
						|
									cache.set(old, { source, comment });
 | 
						|
									return source;
 | 
						|
								}
 | 
						|
								return cached.source;
 | 
						|
							});
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
			);
 | 
						|
		});
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
module.exports = BannerPlugin;
 |