Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 

139 wiersze
3.5 KiB

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