UNPKG

2.65 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const { validate } = require("schema-utils");
9const { ConcatSource } = require("webpack-sources");
10const Compilation = require("./Compilation");
11const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
12const Template = require("./Template");
13
14const schema = require("../schemas/plugins/BannerPlugin.json");
15
16/** @typedef {import("../declarations/plugins/BannerPlugin").BannerPluginArgument} BannerPluginArgument */
17/** @typedef {import("../declarations/plugins/BannerPlugin").BannerPluginOptions} BannerPluginOptions */
18/** @typedef {import("./Compiler")} Compiler */
19
20const wrapComment = str => {
21 if (!str.includes("\n")) {
22 return Template.toComment(str);
23 }
24 return `/*!\n * ${str
25 .replace(/\*\//g, "* /")
26 .split("\n")
27 .join("\n * ")
28 .replace(/\s+\n/g, "\n")
29 .trimRight()}\n */`;
30};
31
32class BannerPlugin {
33 /**
34 * @param {BannerPluginArgument} options options object
35 */
36 constructor(options) {
37 if (typeof options === "string" || typeof options === "function") {
38 options = {
39 banner: options
40 };
41 }
42
43 validate(schema, options, {
44 name: "Banner Plugin",
45 baseDataPath: "options"
46 });
47
48 this.options = options;
49
50 const bannerOption = options.banner;
51 if (typeof bannerOption === "function") {
52 const getBanner = bannerOption;
53 this.banner = this.options.raw
54 ? getBanner
55 : data => wrapComment(getBanner(data));
56 } else {
57 const banner = this.options.raw
58 ? bannerOption
59 : wrapComment(bannerOption);
60 this.banner = () => banner;
61 }
62 }
63
64 /**
65 * Apply the plugin
66 * @param {Compiler} compiler the compiler instance
67 * @returns {void}
68 */
69 apply(compiler) {
70 const options = this.options;
71 const banner = this.banner;
72 const matchObject = ModuleFilenameHelpers.matchObject.bind(
73 undefined,
74 options
75 );
76
77 compiler.hooks.compilation.tap("BannerPlugin", compilation => {
78 compilation.hooks.processAssets.tap(
79 {
80 name: "BannerPlugin",
81 stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
82 },
83 () => {
84 for (const chunk of compilation.chunks) {
85 if (options.entryOnly && !chunk.canBeInitial()) {
86 continue;
87 }
88
89 for (const file of chunk.files) {
90 if (!matchObject(file)) {
91 continue;
92 }
93
94 const data = {
95 chunk,
96 filename: file
97 };
98
99 const comment = compilation.getPath(banner, data);
100
101 compilation.updateAsset(
102 file,
103 old => new ConcatSource(comment, "\n", old)
104 );
105 }
106 }
107 }
108 );
109 });
110 }
111}
112
113module.exports = BannerPlugin;